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 #if defined(TARGET_ANDROID)
79 #include "DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.h"
82 using namespace Shaders;
84 CLinuxRendererGLES::YUVBUFFER::YUVBUFFER()
86 memset(&fields, 0, sizeof(fields));
87 memset(&image , 0, sizeof(image));
89 #ifdef HAVE_LIBOPENMAX
92 #ifdef HAVE_VIDEOTOOLBOXDECODER
95 #ifdef HAS_LIBSTAGEFRIGHT
97 eglimg = EGL_NO_IMAGE_KHR;
99 #if defined(TARGET_ANDROID)
104 CLinuxRendererGLES::YUVBUFFER::~YUVBUFFER()
108 CLinuxRendererGLES::CLinuxRendererGLES()
110 m_textureTarget = GL_TEXTURE_2D;
112 m_renderMethod = RENDER_GLSL;
113 m_oldRenderMethod = m_renderMethod;
114 m_renderQuality = RQ_SINGLEPASS;
116 m_format = RENDER_FMT_NONE;
118 m_iYV12RenderBuffer = 0;
120 m_currentField = FIELD_FULL;
123 m_pVideoFilterShader = NULL;
124 m_scalingMethod = VS_SCALINGMETHOD_LINEAR;
125 m_scalingMethodGui = (ESCALINGMETHOD)-1;
127 // default texture handlers to YUV
128 m_textureUpload = &CLinuxRendererGLES::UploadYV12Texture;
129 m_textureCreate = &CLinuxRendererGLES::CreateYV12Texture;
130 m_textureDelete = &CLinuxRendererGLES::DeleteYV12Texture;
135 m_dllSwScale = new DllSwScale;
137 m_NumYV12Buffers = 0;
138 m_iLastRenderBuffer = 0;
139 m_bConfigured = false;
140 m_bValidated = false;
141 m_bImageReady = false;
142 m_StrictBinding = false;
143 m_clearColour = 0.0f;
145 #ifdef HAS_LIBSTAGEFRIGHT
146 if (!eglCreateImageKHR)
147 eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC) CEGLWrapper::GetProcAddress("eglCreateImageKHR");
148 if (!eglDestroyImageKHR)
149 eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC) CEGLWrapper::GetProcAddress("eglDestroyImageKHR");
150 if (!glEGLImageTargetTexture2DOES)
151 glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) CEGLWrapper::GetProcAddress("glEGLImageTargetTexture2DOES");
155 CLinuxRendererGLES::~CLinuxRendererGLES()
159 if (m_rgbBuffer != NULL) {
160 delete [] m_rgbBuffer;
166 m_pYUVShader->Free();
174 bool CLinuxRendererGLES::ValidateRenderTarget()
178 CLog::Log(LOGNOTICE,"Using GL_TEXTURE_2D");
180 // function pointer for texture might change in
181 // call to LoadShaders
183 for (int i = 0 ; i < NUM_BUFFERS ; i++)
184 (this->*m_textureDelete)(i);
186 // create the yuv textures
189 for (int i = 0 ; i < m_NumYV12Buffers ; i++)
190 (this->*m_textureCreate)(i);
198 bool CLinuxRendererGLES::Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format, unsigned int orientation)
200 m_sourceWidth = width;
201 m_sourceHeight = height;
202 m_renderOrientation = orientation;
208 // Calculate the input frame aspect ratio.
209 CalculateFrameAspectRatio(d_width, d_height);
210 ChooseBestResolution(fps);
211 SetViewMode(CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode);
214 m_bConfigured = true;
215 m_bImageReady = false;
216 m_scalingMethodGui = (ESCALINGMETHOD)-1;
218 // Ensure that textures are recreated and rendering starts only after the 1st
219 // frame is loaded after every call to Configure().
220 m_bValidated = false;
222 for (int i = 0 ; i<m_NumYV12Buffers ; i++)
223 m_buffers[i].image.flags = 0;
225 m_iLastRenderBuffer = -1;
227 m_RenderUpdateCallBackFn = NULL;
228 m_RenderUpdateCallBackCtx = NULL;
229 if ((m_format == RENDER_FMT_BYPASS) && g_application.GetCurrentPlayer())
231 m_renderFeatures.clear();
232 m_scalingMethods.clear();
233 m_deinterlaceModes.clear();
234 m_deinterlaceMethods.clear();
236 if (m_RenderFeaturesCallBackFn)
238 (*m_RenderFeaturesCallBackFn)(m_RenderFeaturesCallBackCtx, m_renderFeatures);
239 // after setting up m_renderFeatures, we are done with the callback
240 m_RenderFeaturesCallBackFn = NULL;
241 m_RenderFeaturesCallBackCtx = NULL;
243 g_application.m_pPlayer->GetRenderFeatures(m_renderFeatures);
244 g_application.m_pPlayer->GetDeinterlaceMethods(m_deinterlaceMethods);
245 g_application.m_pPlayer->GetDeinterlaceModes(m_deinterlaceModes);
246 g_application.m_pPlayer->GetScalingMethods(m_scalingMethods);
252 int CLinuxRendererGLES::NextYV12Texture()
254 return (m_iYV12RenderBuffer + 1) % m_NumYV12Buffers;
257 int CLinuxRendererGLES::GetImage(YV12Image *image, int source, bool readonly)
259 if (!image) return -1;
260 if (!m_bValidated) return -1;
262 /* take next available buffer */
263 if( source == AUTOSOURCE )
264 source = NextYV12Texture();
266 if ( m_renderMethod & RENDER_OMXEGL )
270 #ifdef HAS_LIBSTAGEFRIGHT
271 if ( m_renderMethod & RENDER_EGLIMG )
277 if ( m_renderMethod & RENDER_MEDIACODEC )
282 #ifdef HAVE_VIDEOTOOLBOXDECODER
283 if (m_renderMethod & RENDER_CVREF )
289 YV12Image &im = m_buffers[source].image;
291 if ((im.flags&(~IMAGE_FLAG_READY)) != 0)
293 CLog::Log(LOGDEBUG, "CLinuxRenderer::GetImage - request image but none to give");
298 im.flags |= IMAGE_FLAG_READING;
300 im.flags |= IMAGE_FLAG_WRITING;
302 // copy the image - should be operator of YV12Image
303 for (int p=0;p<MAX_PLANES;p++)
305 image->plane[p] = im.plane[p];
306 image->stride[p] = im.stride[p];
308 image->width = im.width;
309 image->height = im.height;
310 image->flags = im.flags;
311 image->cshift_x = im.cshift_x;
312 image->cshift_y = im.cshift_y;
318 void CLinuxRendererGLES::ReleaseImage(int source, bool preserve)
320 YV12Image &im = m_buffers[source].image;
322 im.flags &= ~IMAGE_FLAG_INUSE;
323 im.flags |= IMAGE_FLAG_READY;
324 /* if image should be preserved reserve it so it's not auto seleceted */
327 im.flags |= IMAGE_FLAG_RESERVED;
329 m_bImageReady = true;
332 void CLinuxRendererGLES::CalculateTextureSourceRects(int source, int num_planes)
334 YUVBUFFER& buf = m_buffers[source];
335 YV12Image* im = &buf.image;
336 YUVFIELDS& fields = buf.fields;
338 // calculate the source rectangle
339 for(int field = 0; field < 3; field++)
341 for(int plane = 0; plane < num_planes; plane++)
343 YUVPLANE& p = fields[field][plane];
345 p.rect = m_sourceRect;
347 p.height = im->height;
349 if(field != FIELD_FULL)
351 /* correct for field offsets and chroma offsets */
352 float offset_y = 0.5;
355 if(field == FIELD_BOT)
358 p.rect.y1 += offset_y;
359 p.rect.y2 += offset_y;
361 /* half the height if this is a field */
369 p.width /= 1 << im->cshift_x;
370 p.height /= 1 << im->cshift_y;
372 p.rect.x1 /= 1 << im->cshift_x;
373 p.rect.x2 /= 1 << im->cshift_x;
374 p.rect.y1 /= 1 << im->cshift_y;
375 p.rect.y2 /= 1 << im->cshift_y;
378 if (m_textureTarget == GL_TEXTURE_2D)
380 p.height /= p.texheight;
381 p.rect.y1 /= p.texheight;
382 p.rect.y2 /= p.texheight;
383 p.width /= p.texwidth;
384 p.rect.x1 /= p.texwidth;
385 p.rect.x2 /= p.texwidth;
391 void CLinuxRendererGLES::LoadPlane( YUVPLANE& plane, int type, unsigned flipindex
392 , unsigned width, unsigned height
393 , unsigned int stride, void* data )
395 if(plane.flipindex == flipindex)
398 const GLvoid *pixelData = data;
400 int bps = glFormatElementByteCount(type);
402 glBindTexture(m_textureTarget, plane.id);
404 // OpenGL ES does not support strided texture input.
405 if(stride != width * bps)
407 unsigned char* src = (unsigned char*)data;
408 for (unsigned int y = 0; y < height;++y, src += stride)
409 glTexSubImage2D(m_textureTarget, 0, 0, y, width, 1, type, GL_UNSIGNED_BYTE, src);
411 glTexSubImage2D(m_textureTarget, 0, 0, 0, width, height, type, GL_UNSIGNED_BYTE, pixelData);
414 /* check if we need to load any border pixels */
415 if(height < plane.texheight)
416 glTexSubImage2D( m_textureTarget, 0
417 , 0, height, width, 1
418 , type, GL_UNSIGNED_BYTE
419 , (unsigned char*)pixelData + stride * (height-1));
421 if(width < plane.texwidth)
422 glTexSubImage2D( m_textureTarget, 0
423 , width, 0, 1, height
424 , type, GL_UNSIGNED_BYTE
425 , (unsigned char*)pixelData + bps * (width-1));
427 glBindTexture(m_textureTarget, 0);
429 plane.flipindex = flipindex;
432 void CLinuxRendererGLES::Reset()
434 for(int i=0; i<m_NumYV12Buffers; i++)
436 /* reset all image flags, this will cleanup textures later */
437 m_buffers[i].image.flags = 0;
441 void CLinuxRendererGLES::Flush()
448 for (int i = 0 ; i < m_NumYV12Buffers ; i++)
449 (this->*m_textureDelete)(i);
452 m_bValidated = false;
454 m_iYV12RenderBuffer = 0;
457 void CLinuxRendererGLES::Update()
459 if (!m_bConfigured) return;
463 void CLinuxRendererGLES::RenderUpdate(bool clear, DWORD flags, DWORD alpha)
465 if (!m_bConfigured) return;
467 // if its first pass, just init textures and return
468 if (ValidateRenderTarget())
471 if (m_renderMethod & RENDER_BYPASS)
474 // if running bypass, then the player might need the src/dst rects
475 // for sizing video playback on a layer other than the gles layer.
476 if (m_RenderUpdateCallBackFn)
477 (*m_RenderUpdateCallBackFn)(m_RenderUpdateCallBackCtx, m_sourceRect, m_destRect);
479 CRect old = g_graphicsContext.GetScissors();
481 g_graphicsContext.BeginPaint();
482 g_graphicsContext.SetScissors(m_destRect);
485 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
486 glClearColor(0, 0, 0, 0);
487 glClear(GL_COLOR_BUFFER_BIT);
489 g_graphicsContext.SetScissors(old);
490 g_graphicsContext.EndPaint();
494 // this needs to be checked after texture validation
495 if (!m_bImageReady) return;
497 int index = m_iYV12RenderBuffer;
498 YUVBUFFER& buf = m_buffers[index];
500 if (m_format != RENDER_FMT_OMXEGL && m_format != RENDER_FMT_EGLIMG && m_format != RENDER_FMT_MEDIACODEC)
502 if (!buf.fields[FIELD_FULL][0].id) return;
504 if (buf.image.flags==0)
509 g_graphicsContext.BeginPaint();
511 m_iLastRenderBuffer = index;
515 glClearColor(m_clearColour, m_clearColour, m_clearColour, 0);
516 glClear(GL_COLOR_BUFFER_BIT);
517 glClearColor(0,0,0,0);
523 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
525 m_pYUVShader->SetAlpha(alpha / 255.0f);
531 m_pYUVShader->SetAlpha(1.0f);
534 if ((flags & RENDER_FLAG_TOP) && (flags & RENDER_FLAG_BOT))
535 CLog::Log(LOGERROR, "GLES: Cannot render stipple!");
537 Render(flags, index);
542 g_graphicsContext.EndPaint();
545 void CLinuxRendererGLES::FlipPage(int source)
547 if( source >= 0 && source < m_NumYV12Buffers )
548 m_iYV12RenderBuffer = source;
550 m_iYV12RenderBuffer = NextYV12Texture();
552 m_buffers[m_iYV12RenderBuffer].flipindex = ++m_flipindex;
557 unsigned int CLinuxRendererGLES::PreInit()
559 CSingleLock lock(g_graphicsContext);
560 m_bConfigured = false;
561 m_bValidated = false;
563 m_resolution = CDisplaySettings::Get().GetCurrentResolution();
564 if ( m_resolution == RES_WINDOW )
565 m_resolution = RES_DESKTOP;
567 m_iYV12RenderBuffer = 0;
568 m_NumYV12Buffers = 2;
570 m_formats.push_back(RENDER_FMT_YUV420P);
571 m_formats.push_back(RENDER_FMT_BYPASS);
572 #if defined(HAVE_LIBOPENMAX)
573 m_formats.push_back(RENDER_FMT_OMXEGL);
575 #ifdef HAVE_VIDEOTOOLBOXDECODER
576 m_formats.push_back(RENDER_FMT_CVBREF);
578 #ifdef HAS_LIBSTAGEFRIGHT
579 m_formats.push_back(RENDER_FMT_EGLIMG);
581 #if defined(TARGET_ANDROID)
582 m_formats.push_back(RENDER_FMT_MEDIACODEC);
585 // setup the background colour
586 m_clearColour = (float)(g_advancedSettings.m_videoBlackBarColour & 0xff) / 0xff;
588 if (!m_dllSwScale->Load())
589 CLog::Log(LOGERROR,"CLinuxRendererGL::PreInit - failed to load rescale libraries!");
594 void CLinuxRendererGLES::UpdateVideoFilter()
596 if (m_scalingMethodGui == CMediaSettings::Get().GetCurrentVideoSettings().m_ScalingMethod)
598 m_scalingMethodGui = CMediaSettings::Get().GetCurrentVideoSettings().m_ScalingMethod;
599 m_scalingMethod = m_scalingMethodGui;
601 if(!Supports(m_scalingMethod))
603 CLog::Log(LOGWARNING, "CLinuxRendererGLES::UpdateVideoFilter - choosen scaling method %d, is not supported by renderer", (int)m_scalingMethod);
604 m_scalingMethod = VS_SCALINGMETHOD_LINEAR;
607 if (m_pVideoFilterShader)
609 m_pVideoFilterShader->Free();
610 delete m_pVideoFilterShader;
611 m_pVideoFilterShader = NULL;
617 switch (m_scalingMethod)
619 case VS_SCALINGMETHOD_NEAREST:
620 SetTextureFilter(GL_NEAREST);
621 m_renderQuality = RQ_SINGLEPASS;
624 case VS_SCALINGMETHOD_LINEAR:
625 SetTextureFilter(GL_LINEAR);
626 m_renderQuality = RQ_SINGLEPASS;
629 case VS_SCALINGMETHOD_CUBIC:
630 CLog::Log(LOGERROR, "GLES: CUBIC not supported!");
633 case VS_SCALINGMETHOD_LANCZOS2:
634 case VS_SCALINGMETHOD_LANCZOS3:
635 case VS_SCALINGMETHOD_SINC8:
636 case VS_SCALINGMETHOD_NEDI:
637 CLog::Log(LOGERROR, "GL: TODO: This scaler has not yet been implemented");
644 CGUIDialogKaiToast::QueueNotification("Video Renderering", "Failed to init video filters/scalers, falling back to bilinear scaling");
645 CLog::Log(LOGERROR, "GL: Falling back to bilinear due to failure to init scaler");
646 if (m_pVideoFilterShader)
648 m_pVideoFilterShader->Free();
649 delete m_pVideoFilterShader;
650 m_pVideoFilterShader = NULL;
654 SetTextureFilter(GL_LINEAR);
655 m_renderQuality = RQ_SINGLEPASS;
658 void CLinuxRendererGLES::LoadShaders(int field)
660 #ifdef TARGET_DARWIN_IOS
661 float ios_version = GetIOSVersion();
663 int requestedMethod = CSettings::Get().GetInt("videoplayer.rendermethod");
664 CLog::Log(LOGDEBUG, "GL: Requested render method: %d", requestedMethod);
668 m_pYUVShader->Free();
673 switch(requestedMethod)
675 case RENDER_METHOD_AUTO:
676 case RENDER_METHOD_GLSL:
677 if (m_format == RENDER_FMT_OMXEGL)
679 CLog::Log(LOGNOTICE, "GL: Using OMXEGL RGBA render method");
680 m_renderMethod = RENDER_OMXEGL;
683 else if (m_format == RENDER_FMT_EGLIMG)
685 CLog::Log(LOGNOTICE, "GL: Using EGL Image render method");
686 m_renderMethod = RENDER_EGLIMG;
689 else if (m_format == RENDER_FMT_MEDIACODEC)
691 CLog::Log(LOGNOTICE, "GL: Using MediaCodec render method");
692 m_renderMethod = RENDER_MEDIACODEC;
695 else if (m_format == RENDER_FMT_BYPASS)
697 CLog::Log(LOGNOTICE, "GL: Using BYPASS render method");
698 m_renderMethod = RENDER_BYPASS;
701 else if (m_format == RENDER_FMT_CVBREF)
703 CLog::Log(LOGNOTICE, "GL: Using CoreVideoRef RGBA render method");
704 m_renderMethod = RENDER_CVREF;
707 #if defined(TARGET_DARWIN_IOS)
708 else if (ios_version < 5.0 && m_format == RENDER_FMT_YUV420P)
710 CLog::Log(LOGNOTICE, "GL: Using software color conversion/RGBA render method");
711 m_renderMethod = RENDER_SW;
715 // Try GLSL shaders if supported and user requested auto or GLSL.
718 // create regular progressive scan shader
719 m_pYUVShader = new YUV2RGBProgressiveShader(false, m_iFlags, m_format);
720 CLog::Log(LOGNOTICE, "GL: Selecting Single Pass YUV 2 RGB shader");
722 if (m_pYUVShader && m_pYUVShader->CompileAndLink())
724 m_renderMethod = RENDER_GLSL;
728 else if (m_pYUVShader)
730 m_pYUVShader->Free();
733 CLog::Log(LOGERROR, "GL: Error enabling YUV2RGB GLSL shader");
734 // drop through and try SW
737 case RENDER_METHOD_SOFTWARE:
740 // Use software YUV 2 RGB conversion if user requested it or GLSL failed
741 m_renderMethod = RENDER_SW ;
742 CLog::Log(LOGNOTICE, "GL: Using software color conversion/RGBA rendering");
746 // determine whether GPU supports NPOT textures
747 if (!g_Windowing.IsExtSupported("GL_TEXTURE_NPOT"))
749 CLog::Log(LOGNOTICE, "GL: GL_ARB_texture_rectangle not supported and OpenGL version is not 2.x");
750 CLog::Log(LOGNOTICE, "GL: Reverting to POT textures");
751 m_renderMethod |= RENDER_POT;
754 CLog::Log(LOGNOTICE, "GL: NPOT texture support detected");
756 // Now that we now the render method, setup texture function handlers
757 if (m_format == RENDER_FMT_CVBREF)
759 m_textureUpload = &CLinuxRendererGLES::UploadCVRefTexture;
760 m_textureCreate = &CLinuxRendererGLES::CreateCVRefTexture;
761 m_textureDelete = &CLinuxRendererGLES::DeleteCVRefTexture;
763 else if (m_format == RENDER_FMT_BYPASS)
765 m_textureUpload = &CLinuxRendererGLES::UploadBYPASSTexture;
766 m_textureCreate = &CLinuxRendererGLES::CreateBYPASSTexture;
767 m_textureDelete = &CLinuxRendererGLES::DeleteBYPASSTexture;
769 else if (m_format == RENDER_FMT_EGLIMG)
771 m_textureUpload = &CLinuxRendererGLES::UploadEGLIMGTexture;
772 m_textureCreate = &CLinuxRendererGLES::CreateEGLIMGTexture;
773 m_textureDelete = &CLinuxRendererGLES::DeleteEGLIMGTexture;
775 else if (m_format == RENDER_FMT_MEDIACODEC)
777 m_textureUpload = &CLinuxRendererGLES::UploadSurfaceTexture;
778 m_textureCreate = &CLinuxRendererGLES::CreateSurfaceTexture;
779 m_textureDelete = &CLinuxRendererGLES::DeleteSurfaceTexture;
784 // default to YV12 texture handlers
785 m_textureUpload = &CLinuxRendererGLES::UploadYV12Texture;
786 m_textureCreate = &CLinuxRendererGLES::CreateYV12Texture;
787 m_textureDelete = &CLinuxRendererGLES::DeleteYV12Texture;
790 if (m_oldRenderMethod != m_renderMethod)
792 CLog::Log(LOGDEBUG, "CLinuxRendererGLES: Reorder drawpoints due to method change from %i to %i", m_oldRenderMethod, m_renderMethod);
794 m_oldRenderMethod = m_renderMethod;
798 void CLinuxRendererGLES::UnInit()
800 CLog::Log(LOGDEBUG, "LinuxRendererGL: Cleaning up GL resources");
801 CSingleLock lock(g_graphicsContext);
803 if (m_rgbBuffer != NULL)
805 delete [] m_rgbBuffer;
811 for (int i = 0; i < NUM_BUFFERS; ++i)
812 (this->*m_textureDelete)(i);
814 if (m_dllSwScale && m_sw_context)
816 m_dllSwScale->sws_freeContext(m_sw_context);
820 // cleanup framebuffer object if it was in use
822 m_bValidated = false;
823 m_bImageReady = false;
824 m_bConfigured = false;
825 m_RenderUpdateCallBackFn = NULL;
826 m_RenderUpdateCallBackCtx = NULL;
827 m_RenderFeaturesCallBackFn = NULL;
828 m_RenderFeaturesCallBackCtx = NULL;
831 inline void CLinuxRendererGLES::ReorderDrawPoints()
834 CBaseRenderer::ReorderDrawPoints();//call base impl. for rotating the points
836 //corevideo and EGL are flipped in y
837 if(m_renderMethod & RENDER_CVREF)
840 tmp = m_rotatedDestCoords[0];
841 m_rotatedDestCoords[0] = m_rotatedDestCoords[3];
842 m_rotatedDestCoords[3] = tmp;
843 tmp = m_rotatedDestCoords[1];
844 m_rotatedDestCoords[1] = m_rotatedDestCoords[2];
845 m_rotatedDestCoords[2] = tmp;
849 void CLinuxRendererGLES::ReleaseBuffer(int idx)
851 #ifdef HAVE_VIDEOTOOLBOXDECODER
852 YUVBUFFER &buf = m_buffers[idx];
855 CVBufferRelease(buf.cvBufferRef);
856 buf.cvBufferRef = NULL;
858 #if defined(TARGET_ANDROID)
859 YUVBUFFER &buf = m_buffers[idx];
861 SAFE_RELEASE(m_buffers[idx].mediacodec);
865 void CLinuxRendererGLES::Render(DWORD flags, int index)
867 // If rendered directly by the hardware
868 if (m_renderMethod & RENDER_BYPASS)
871 // obtain current field, if interlaced
872 if( flags & RENDER_FLAG_TOP)
873 m_currentField = FIELD_TOP;
875 else if (flags & RENDER_FLAG_BOT)
876 m_currentField = FIELD_BOT;
879 m_currentField = FIELD_FULL;
881 (this->*m_textureUpload)(index);
883 if (m_renderMethod & RENDER_GLSL)
886 switch(m_renderQuality)
890 RenderSinglePass(index, m_currentField);
895 RenderMultiPass(index, m_currentField);
900 RenderSoftware(index, m_currentField);
905 else if (m_renderMethod & RENDER_OMXEGL)
907 RenderOpenMax(index, m_currentField);
910 else if (m_renderMethod & RENDER_EGLIMG)
912 RenderEglImage(index, m_currentField);
915 else if (m_renderMethod & RENDER_CVREF)
917 RenderCoreVideoRef(index, m_currentField);
920 else if (m_renderMethod & RENDER_MEDIACODEC)
922 RenderMediaCodec(index, m_currentField);
926 RenderSoftware(index, m_currentField);
931 void CLinuxRendererGLES::RenderSinglePass(int index, int field)
933 YV12Image &im = m_buffers[index].image;
934 YUVFIELDS &fields = m_buffers[index].fields;
935 YUVPLANES &planes = fields[field];
943 glDisable(GL_DEPTH_TEST);
946 glActiveTexture(GL_TEXTURE0);
947 glEnable(m_textureTarget);
948 glBindTexture(m_textureTarget, planes[0].id);
951 glActiveTexture(GL_TEXTURE1);
952 glEnable(m_textureTarget);
953 glBindTexture(m_textureTarget, planes[1].id);
956 glActiveTexture(GL_TEXTURE2);
957 glEnable(m_textureTarget);
958 glBindTexture(m_textureTarget, planes[2].id);
960 glActiveTexture(GL_TEXTURE0);
963 m_pYUVShader->SetBlack(CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness * 0.01f - 0.5f);
964 m_pYUVShader->SetContrast(CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast * 0.02f);
965 m_pYUVShader->SetWidth(im.width);
966 m_pYUVShader->SetHeight(im.height);
967 if (field == FIELD_TOP)
968 m_pYUVShader->SetField(1);
969 else if(field == FIELD_BOT)
970 m_pYUVShader->SetField(0);
972 m_pYUVShader->SetMatrices(g_matrices.GetMatrix(MM_PROJECTION), g_matrices.GetMatrix(MM_MODELVIEW));
973 m_pYUVShader->Enable();
975 GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip
976 GLfloat m_vert[4][3];
977 GLfloat m_tex[3][4][2];
979 GLint vertLoc = m_pYUVShader->GetVertexLoc();
980 GLint Yloc = m_pYUVShader->GetYcoordLoc();
981 GLint Uloc = m_pYUVShader->GetUcoordLoc();
982 GLint Vloc = m_pYUVShader->GetVcoordLoc();
984 glVertexAttribPointer(vertLoc, 3, GL_FLOAT, 0, 0, m_vert);
985 glVertexAttribPointer(Yloc, 2, GL_FLOAT, 0, 0, m_tex[0]);
986 glVertexAttribPointer(Uloc, 2, GL_FLOAT, 0, 0, m_tex[1]);
987 glVertexAttribPointer(Vloc, 2, GL_FLOAT, 0, 0, m_tex[2]);
989 glEnableVertexAttribArray(vertLoc);
990 glEnableVertexAttribArray(Yloc);
991 glEnableVertexAttribArray(Uloc);
992 glEnableVertexAttribArray(Vloc);
994 // Setup vertex position values
995 for(int i = 0; i < 4; i++)
997 m_vert[i][0] = m_rotatedDestCoords[i].x;
998 m_vert[i][1] = m_rotatedDestCoords[i].y;
999 m_vert[i][2] = 0.0f;// set z to 0
1002 // Setup texture coordinates
1003 for (int i=0; i<3; i++)
1005 m_tex[i][0][0] = m_tex[i][3][0] = planes[i].rect.x1;
1006 m_tex[i][0][1] = m_tex[i][1][1] = planes[i].rect.y1;
1007 m_tex[i][1][0] = m_tex[i][2][0] = planes[i].rect.x2;
1008 m_tex[i][2][1] = m_tex[i][3][1] = planes[i].rect.y2;
1011 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1015 m_pYUVShader->Disable();
1018 glDisableVertexAttribArray(vertLoc);
1019 glDisableVertexAttribArray(Yloc);
1020 glDisableVertexAttribArray(Uloc);
1021 glDisableVertexAttribArray(Vloc);
1023 glActiveTexture(GL_TEXTURE1);
1024 glDisable(m_textureTarget);
1026 glActiveTexture(GL_TEXTURE2);
1027 glDisable(m_textureTarget);
1029 glActiveTexture(GL_TEXTURE0);
1030 glDisable(m_textureTarget);
1032 g_matrices.MatrixMode(MM_MODELVIEW);
1037 void CLinuxRendererGLES::RenderMultiPass(int index, int field)
1039 // TODO: Multipass rendering does not currently work! FIX!
1040 CLog::Log(LOGERROR, "GLES: MULTIPASS rendering was called! But it doesnt work!!!");
1043 YV12Image &im = m_buffers[index].image;
1044 YUVPLANES &planes = m_buffers[index].fields[field];
1046 if (m_reloadShaders)
1048 m_reloadShaders = 0;
1049 LoadShaders(m_currentField);
1052 glDisable(GL_DEPTH_TEST);
1055 glEnable(m_textureTarget);
1056 glActiveTexture(GL_TEXTURE0);
1057 glBindTexture(m_textureTarget, planes[0].id);
1061 glActiveTexture(GL_TEXTURE1);
1062 glEnable(m_textureTarget);
1063 glBindTexture(m_textureTarget, planes[1].id);
1067 glActiveTexture(GL_TEXTURE2);
1068 glEnable(m_textureTarget);
1069 glBindTexture(m_textureTarget, planes[2].id);
1072 glActiveTexture(GL_TEXTURE0);
1075 // make sure the yuv shader is loaded and ready to go
1076 if (!m_pYUVShader || (!m_pYUVShader->OK()))
1078 CLog::Log(LOGERROR, "GL: YUV shader not active, cannot do multipass render");
1082 m_fbo.BeginRender();
1085 m_pYUVShader->SetBlack(CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness * 0.01f - 0.5f);
1086 m_pYUVShader->SetContrast(CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast * 0.02f);
1087 m_pYUVShader->SetWidth(im.width);
1088 m_pYUVShader->SetHeight(im.height);
1089 if (field == FIELD_TOP)
1090 m_pYUVShader->SetField(1);
1091 else if(field == FIELD_BOT)
1092 m_pYUVShader->SetField(0);
1096 // glPushAttrib(GL_VIEWPORT_BIT);
1097 // glPushAttrib(GL_SCISSOR_BIT);
1098 g_matrices.MatrixMode(MM_MODELVIEW);
1099 g_matrices.PushMatrix();
1100 g_matrices.LoadIdentity();
1103 g_matrices.MatrixMode(MM_PROJECTION);
1104 g_matrices.PushMatrix();
1105 g_matrices.LoadIdentity();
1107 g_matrices.Ortho2D(0, m_sourceWidth, 0, m_sourceHeight);
1108 glViewport(0, 0, m_sourceWidth, m_sourceHeight);
1109 glScissor(0, 0, m_sourceWidth, m_sourceHeight);
1110 g_matrices.MatrixMode(MM_MODELVIEW);
1114 if (!m_pYUVShader->Enable())
1116 CLog::Log(LOGERROR, "GL: Error enabling YUV shader");
1119 // 1st Pass to video frame size
1121 // float imgwidth = planes[0].rect.x2 - planes[0].rect.x1;
1122 // float imgheight = planes[0].rect.y2 - planes[0].rect.y1;
1123 // if (m_textureTarget == GL_TEXTURE_2D)
1125 // imgwidth *= planes[0].texwidth;
1126 // imgheight *= planes[0].texheight;
1129 // glBegin(GL_QUADS);
1131 // glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x1, planes[0].rect.y1);
1132 // glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x1, planes[1].rect.y1);
1133 // glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x1, planes[2].rect.y1);
1134 // glVertex2f(0.0f , 0.0f);
1136 // glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x2, planes[0].rect.y1);
1137 // glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x2, planes[1].rect.y1);
1138 // glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x2, planes[2].rect.y1);
1139 // glVertex2f(imgwidth, 0.0f);
1141 // glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x2, planes[0].rect.y2);
1142 // glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x2, planes[1].rect.y2);
1143 // glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x2, planes[2].rect.y2);
1144 // glVertex2f(imgwidth, imgheight);
1146 // glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x1, planes[0].rect.y2);
1147 // glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x1, planes[1].rect.y2);
1148 // glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x1, planes[2].rect.y2);
1149 // glVertex2f(0.0f , imgheight);
1154 m_pYUVShader->Disable();
1156 g_matrices.MatrixMode(MM_MODELVIEW);
1157 g_matrices.PopMatrix(); // pop modelview
1158 g_matrices.MatrixMode(MM_PROJECTION);
1159 g_matrices.PopMatrix(); // pop projection
1161 // glPopAttrib(); // pop scissor
1162 // glPopAttrib(); // pop viewport
1163 g_matrices.MatrixMode(MM_MODELVIEW);
1168 glActiveTexture(GL_TEXTURE1);
1169 glDisable(m_textureTarget);
1170 glActiveTexture(GL_TEXTURE2);
1171 glDisable(m_textureTarget);
1172 glActiveTexture(GL_TEXTURE0);
1173 glDisable(m_textureTarget);
1175 glEnable(GL_TEXTURE_2D);
1176 glBindTexture(GL_TEXTURE_2D, m_fbo.Texture());
1179 // Use regular normalized texture coordinates
1181 // 2nd Pass to screen size with optional video filter
1183 if (m_pVideoFilterShader)
1185 m_fbo.SetFiltering(GL_TEXTURE_2D, GL_NEAREST);
1186 m_pVideoFilterShader->SetSourceTexture(0);
1187 m_pVideoFilterShader->SetWidth(m_sourceWidth);
1188 m_pVideoFilterShader->SetHeight(m_sourceHeight);
1189 m_pVideoFilterShader->Enable();
1192 m_fbo.SetFiltering(GL_TEXTURE_2D, GL_LINEAR);
1197 // imgwidth /= m_sourceWidth;
1198 // imgheight /= m_sourceHeight;
1200 // glBegin(GL_QUADS);
1202 // glMultiTexCoord2fARB(GL_TEXTURE0, 0.0f , 0.0f);
1203 // glVertex4f(m_destRect.x1, m_destRect.y1, 0, 1.0f );
1205 // glMultiTexCoord2fARB(GL_TEXTURE0, imgwidth, 0.0f);
1206 // glVertex4f(m_destRect.x2, m_destRect.y1, 0, 1.0f);
1208 // glMultiTexCoord2fARB(GL_TEXTURE0, imgwidth, imgheight);
1209 // glVertex4f(m_destRect.x2, m_destRect.y2, 0, 1.0f);
1211 // glMultiTexCoord2fARB(GL_TEXTURE0, 0.0f , imgheight);
1212 // glVertex4f(m_destRect.x1, m_destRect.y2, 0, 1.0f);
1218 if (m_pVideoFilterShader)
1219 m_pVideoFilterShader->Disable();
1223 glDisable(m_textureTarget);
1227 void CLinuxRendererGLES::RenderSoftware(int index, int field)
1229 YUVPLANES &planes = m_buffers[index].fields[field];
1231 glDisable(GL_DEPTH_TEST);
1234 glEnable(m_textureTarget);
1235 glActiveTexture(GL_TEXTURE0);
1236 glBindTexture(m_textureTarget, planes[0].id);
1238 g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA);
1240 GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip
1243 GLfloat col[3] = {1.0f, 1.0f, 1.0f};
1245 GLint posLoc = g_Windowing.GUIShaderGetPos();
1246 GLint texLoc = g_Windowing.GUIShaderGetCoord0();
1247 GLint colLoc = g_Windowing.GUIShaderGetCol();
1249 glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1250 glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex);
1251 glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
1253 glEnableVertexAttribArray(posLoc);
1254 glEnableVertexAttribArray(texLoc);
1255 glEnableVertexAttribArray(colLoc);
1257 // Set vertex coordinates
1258 for(int i = 0; i < 4; i++)
1260 ver[i][0] = m_rotatedDestCoords[i].x;
1261 ver[i][1] = m_rotatedDestCoords[i].y;
1262 ver[i][2] = 0.0f;// set z to 0
1266 // Set texture coordinates
1267 tex[0][0] = tex[3][0] = planes[0].rect.x1;
1268 tex[0][1] = tex[1][1] = planes[0].rect.y1;
1269 tex[1][0] = tex[2][0] = planes[0].rect.x2;
1270 tex[2][1] = tex[3][1] = planes[0].rect.y2;
1272 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1274 glDisableVertexAttribArray(posLoc);
1275 glDisableVertexAttribArray(texLoc);
1276 glDisableVertexAttribArray(colLoc);
1278 g_Windowing.DisableGUIShader();
1282 glDisable(m_textureTarget);
1286 void CLinuxRendererGLES::RenderOpenMax(int index, int field)
1288 #if defined(HAVE_LIBOPENMAX)
1289 GLuint textureId = m_buffers[index].openMaxBuffer->texture_id;
1291 glDisable(GL_DEPTH_TEST);
1294 glEnable(m_textureTarget);
1295 glActiveTexture(GL_TEXTURE0);
1296 glBindTexture(m_textureTarget, textureId);
1298 g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA);
1300 GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip
1303 GLfloat col[3] = {1.0f, 1.0f, 1.0f};
1305 GLint posLoc = g_Windowing.GUIShaderGetPos();
1306 GLint texLoc = g_Windowing.GUIShaderGetCoord0();
1307 GLint colLoc = g_Windowing.GUIShaderGetCol();
1309 glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1310 glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex);
1311 glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
1313 glEnableVertexAttribArray(posLoc);
1314 glEnableVertexAttribArray(texLoc);
1315 glEnableVertexAttribArray(colLoc);
1317 // Set vertex coordinates
1318 for(int i = 0; i < 4; i++)
1320 ver[i][0] = m_rotatedDestCoords[i].x;
1321 ver[i][1] = m_rotatedDestCoords[i].y;
1322 ver[i][2] = 0.0f;// set z to 0
1326 // Set texture coordinates
1327 tex[0][0] = tex[3][0] = 0;
1328 tex[0][1] = tex[1][1] = 0;
1329 tex[1][0] = tex[2][0] = 1;
1330 tex[2][1] = tex[3][1] = 1;
1332 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1334 glDisableVertexAttribArray(posLoc);
1335 glDisableVertexAttribArray(texLoc);
1336 glDisableVertexAttribArray(colLoc);
1338 g_Windowing.DisableGUIShader();
1342 glDisable(m_textureTarget);
1347 void CLinuxRendererGLES::RenderEglImage(int index, int field)
1349 #if defined(HAS_LIBSTAGEFRIGHT)
1350 #ifdef DEBUG_VERBOSE
1351 unsigned int time = XbmcThreads::SystemClockMillis();
1354 YUVPLANE &plane = m_buffers[index].fields[field][0];
1356 glDisable(GL_DEPTH_TEST);
1358 glActiveTexture(GL_TEXTURE0);
1359 glBindTexture(m_textureTarget, plane.id);
1361 g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA);
1363 GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip
1366 GLfloat col[3] = {1.0f, 1.0f, 1.0f};
1368 GLint posLoc = g_Windowing.GUIShaderGetPos();
1369 GLint texLoc = g_Windowing.GUIShaderGetCoord0();
1370 GLint colLoc = g_Windowing.GUIShaderGetCol();
1372 glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1373 glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex);
1374 glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
1376 glEnableVertexAttribArray(posLoc);
1377 glEnableVertexAttribArray(texLoc);
1378 glEnableVertexAttribArray(colLoc);
1380 // Set vertex coordinates
1381 for(int i = 0; i < 4; i++)
1383 ver[i][0] = m_rotatedDestCoords[i].x;
1384 ver[i][1] = m_rotatedDestCoords[i].y;
1385 ver[i][2] = 0.0f;// set z to 0
1389 // Set texture coordinates (is flipped in y)
1390 tex[0][0] = tex[3][0] = 0;
1391 tex[0][1] = tex[1][1] = 1;
1392 tex[1][0] = tex[2][0] = 1;
1393 tex[2][1] = tex[3][1] = 0;
1395 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1397 glDisableVertexAttribArray(posLoc);
1398 glDisableVertexAttribArray(texLoc);
1399 glDisableVertexAttribArray(colLoc);
1401 g_Windowing.DisableGUIShader();
1404 glBindTexture(m_textureTarget, 0);
1407 #ifdef DEBUG_VERBOSE
1408 CLog::Log(LOGDEBUG, "RenderEglImage %d: tm:%d\n", index, XbmcThreads::SystemClockMillis() - time);
1413 void CLinuxRendererGLES::RenderMediaCodec(int index, int field)
1415 #if defined(TARGET_ANDROID)
1416 #ifdef DEBUG_VERBOSE
1417 unsigned int time = XbmcThreads::SystemClockMillis();
1420 YUVPLANE &plane = m_buffers[index].fields[0][0];
1422 glDisable(GL_DEPTH_TEST);
1424 glActiveTexture(GL_TEXTURE0);
1425 glBindTexture(GL_TEXTURE_EXTERNAL_OES, plane.id);
1427 g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA_OES);
1429 glUniformMatrix4fv(g_Windowing.GUIShaderGetCoord0Matrix(), 1, GL_FALSE, m_textureMatrix);
1431 GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip
1435 GLint posLoc = g_Windowing.GUIShaderGetPos();
1436 GLint texLoc = g_Windowing.GUIShaderGetCoord0();
1439 glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1440 glVertexAttribPointer(texLoc, 4, GL_FLOAT, 0, 0, tex);
1442 glEnableVertexAttribArray(posLoc);
1443 glEnableVertexAttribArray(texLoc);
1445 // Set vertex coordinates
1446 for(int i = 0; i < 4; i++)
1448 ver[i][0] = m_rotatedDestCoords[i].x;
1449 ver[i][1] = m_rotatedDestCoords[i].y;
1450 ver[i][2] = 0.0f; // set z to 0
1454 // Set texture coordinates (MediaCodec is flipped in y)
1455 tex[0][0] = tex[3][0] = 0.0f;
1456 tex[0][1] = tex[1][1] = 1.0f;
1457 tex[1][0] = tex[2][0] = 1.0f;
1458 tex[2][1] = tex[3][1] = 0.0f;
1460 for(int i = 0; i < 4; i++)
1466 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1468 glDisableVertexAttribArray(posLoc);
1469 glDisableVertexAttribArray(texLoc);
1471 const float identity[16] = {
1472 1.0f, 0.0f, 0.0f, 0.0f,
1473 0.0f, 1.0f, 0.0f, 0.0f,
1474 0.0f, 0.0f, 1.0f, 0.0f,
1475 0.0f, 0.0f, 0.0f, 1.0f
1477 glUniformMatrix4fv(g_Windowing.GUIShaderGetCoord0Matrix(), 1, GL_FALSE, identity);
1479 g_Windowing.DisableGUIShader();
1482 glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
1485 #ifdef DEBUG_VERBOSE
1486 CLog::Log(LOGDEBUG, "RenderMediaCodecImage %d: tm:%d", index, XbmcThreads::SystemClockMillis() - time);
1491 void CLinuxRendererGLES::RenderCoreVideoRef(int index, int field)
1493 #ifdef HAVE_VIDEOTOOLBOXDECODER
1494 YUVPLANE &plane = m_buffers[index].fields[field][0];
1496 glDisable(GL_DEPTH_TEST);
1498 glEnable(m_textureTarget);
1499 glActiveTexture(GL_TEXTURE0);
1500 glBindTexture(m_textureTarget, plane.id);
1502 g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA);
1504 GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip
1507 GLfloat col[3] = {1.0f, 1.0f, 1.0f};
1509 GLint posLoc = g_Windowing.GUIShaderGetPos();
1510 GLint texLoc = g_Windowing.GUIShaderGetCoord0();
1511 GLint colLoc = g_Windowing.GUIShaderGetCol();
1513 glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1514 glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex);
1515 glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
1517 glEnableVertexAttribArray(posLoc);
1518 glEnableVertexAttribArray(texLoc);
1519 glEnableVertexAttribArray(colLoc);
1521 // Set vertex coordinates
1522 for(int i = 0; i < 4; i++)
1524 ver[i][0] = m_rotatedDestCoords[i].x;
1525 ver[i][1] = m_rotatedDestCoords[i].y;
1526 ver[i][2] = 0.0f;// set z to 0
1530 // Set texture coordinates (corevideo is flipped in y)
1531 tex[0][0] = tex[3][0] = 0;
1532 tex[0][1] = tex[1][1] = 1;
1533 tex[1][0] = tex[2][0] = 1;
1534 tex[2][1] = tex[3][1] = 0;
1536 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1538 glDisableVertexAttribArray(posLoc);
1539 glDisableVertexAttribArray(texLoc);
1540 glDisableVertexAttribArray(colLoc);
1542 g_Windowing.DisableGUIShader();
1545 glDisable(m_textureTarget);
1550 bool CLinuxRendererGLES::RenderCapture(CRenderCapture* capture)
1555 // If rendered directly by the hardware
1556 if (m_renderMethod & RENDER_BYPASS)
1558 capture->BeginRender();
1559 capture->EndRender();
1563 // save current video rect
1564 CRect saveSize = m_destRect;
1565 saveRotatedCoords();//backup current m_rotatedDestCoords
1567 // new video rect is thumbnail size
1568 m_destRect.SetRect(0, 0, (float)capture->GetWidth(), (float)capture->GetHeight());
1570 syncDestRectToRotatedPoints();//syncs the changed destRect to m_rotatedDestCoords
1571 // clear framebuffer and invert Y axis to get non-inverted image
1572 glDisable(GL_BLEND);
1574 g_matrices.MatrixMode(MM_MODELVIEW);
1575 g_matrices.PushMatrix();
1576 // fixme - we know that cvref & eglimg are already flipped in y direction
1577 // but somehow this also effects the rendercapture here
1578 // therefore we have to skip the flip here or we get upside down
1580 if (m_renderMethod != RENDER_CVREF)
1582 g_matrices.Translatef(0.0f, capture->GetHeight(), 0.0f);
1583 g_matrices.Scalef(1.0f, -1.0f, 1.0f);
1586 capture->BeginRender();
1588 Render(RENDER_FLAG_NOOSD, m_iYV12RenderBuffer);
1590 glReadPixels(0, g_graphicsContext.GetHeight() - capture->GetHeight(), capture->GetWidth(), capture->GetHeight(),
1591 GL_RGBA, GL_UNSIGNED_BYTE, capture->GetRenderBuffer());
1593 // OpenGLES returns in RGBA order but CRenderCapture needs BGRA order
1594 // XOR Swap RGBA -> BGRA
1595 unsigned char* pixels = (unsigned char*)capture->GetRenderBuffer();
1596 for (unsigned int i = 0; i < capture->GetWidth() * capture->GetHeight(); i++, pixels+=4)
1598 std::swap(pixels[0], pixels[2]);
1601 capture->EndRender();
1603 // revert model view matrix
1604 g_matrices.MatrixMode(MM_MODELVIEW);
1605 g_matrices.PopMatrix();
1607 // restore original video rect
1608 m_destRect = saveSize;
1609 restoreRotatedCoords();//restores the previous state of the rotated dest coords
1614 //********************************************************************************************************
1615 // YV12 Texture creation, deletion, copying + clearing
1616 //********************************************************************************************************
1617 void CLinuxRendererGLES::UploadYV12Texture(int source)
1619 YUVBUFFER& buf = m_buffers[source];
1620 YV12Image* im = &buf.image;
1621 YUVFIELDS& fields = buf.fields;
1624 #if defined(HAVE_LIBOPENMAX)
1625 if (!(im->flags&IMAGE_FLAG_READY) || m_buffers[source].openMaxBuffer)
1627 if (!(im->flags&IMAGE_FLAG_READY))
1633 // if we don't have a shader, fallback to SW YUV2RGB for now
1634 if (m_renderMethod & RENDER_SW)
1636 if(m_rgbBufferSize < m_sourceWidth * m_sourceHeight * 4)
1638 delete [] m_rgbBuffer;
1639 m_rgbBufferSize = m_sourceWidth*m_sourceHeight*4;
1640 m_rgbBuffer = new BYTE[m_rgbBufferSize];
1643 #if defined(__ARM_NEON__)
1644 if (g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_NEON)
1646 yuv420_2_rgb8888_neon(m_rgbBuffer, im->plane[0], im->plane[2], im->plane[1],
1647 m_sourceWidth, m_sourceHeight, im->stride[0], im->stride[1], m_sourceWidth * 4);
1652 m_sw_context = m_dllSwScale->sws_getCachedContext(m_sw_context,
1653 im->width, im->height, PIX_FMT_YUV420P,
1654 im->width, im->height, PIX_FMT_RGBA,
1655 SWS_FAST_BILINEAR, NULL, NULL, NULL);
1657 uint8_t *src[] = { im->plane[0], im->plane[1], im->plane[2], 0 };
1658 int srcStride[] = { im->stride[0], im->stride[1], im->stride[2], 0 };
1659 uint8_t *dst[] = { m_rgbBuffer, 0, 0, 0 };
1660 int dstStride[] = { m_sourceWidth*4, 0, 0, 0 };
1661 m_dllSwScale->sws_scale(m_sw_context, src, srcStride, 0, im->height, dst, dstStride);
1666 if (m_currentField == FIELD_FULL)
1667 deinterlacing = false;
1669 deinterlacing = true;
1671 glEnable(m_textureTarget);
1674 if (m_renderMethod & RENDER_SW)
1679 LoadPlane( fields[FIELD_TOP][0] , GL_RGBA, buf.flipindex
1680 , im->width, im->height >> 1
1681 , m_sourceWidth*8, m_rgbBuffer );
1683 LoadPlane( fields[FIELD_BOT][0], GL_RGBA, buf.flipindex
1684 , im->width, im->height >> 1
1685 , m_sourceWidth*8, m_rgbBuffer + m_sourceWidth*4);
1689 LoadPlane( fields[FIELD_FULL][0], GL_RGBA, buf.flipindex
1690 , im->width, im->height
1691 , m_sourceWidth*4, m_rgbBuffer );
1696 glPixelStorei(GL_UNPACK_ALIGNMENT,1);
1701 LoadPlane( fields[FIELD_TOP][0] , GL_LUMINANCE, buf.flipindex
1702 , im->width, im->height >> 1
1703 , im->stride[0]*2, im->plane[0] );
1705 LoadPlane( fields[FIELD_BOT][0], GL_LUMINANCE, buf.flipindex
1706 , im->width, im->height >> 1
1707 , im->stride[0]*2, im->plane[0] + im->stride[0]) ;
1712 LoadPlane( fields[FIELD_FULL][0], GL_LUMINANCE, buf.flipindex
1713 , im->width, im->height
1714 , im->stride[0], im->plane[0] );
1720 if (!(m_renderMethod & RENDER_SW))
1722 glPixelStorei(GL_UNPACK_ALIGNMENT,1);
1726 // Load Even U & V Fields
1727 LoadPlane( fields[FIELD_TOP][1], GL_LUMINANCE, buf.flipindex
1728 , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
1729 , im->stride[1]*2, im->plane[1] );
1731 LoadPlane( fields[FIELD_TOP][2], GL_LUMINANCE, buf.flipindex
1732 , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
1733 , im->stride[2]*2, im->plane[2] );
1735 // Load Odd U & V Fields
1736 LoadPlane( fields[FIELD_BOT][1], GL_LUMINANCE, buf.flipindex
1737 , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
1738 , im->stride[1]*2, im->plane[1] + im->stride[1] );
1740 LoadPlane( fields[FIELD_BOT][2], GL_LUMINANCE, buf.flipindex
1741 , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
1742 , im->stride[2]*2, im->plane[2] + im->stride[2] );
1747 LoadPlane( fields[FIELD_FULL][1], GL_LUMINANCE, buf.flipindex
1748 , im->width >> im->cshift_x, im->height >> im->cshift_y
1749 , im->stride[1], im->plane[1] );
1751 LoadPlane( fields[FIELD_FULL][2], GL_LUMINANCE, buf.flipindex
1752 , im->width >> im->cshift_x, im->height >> im->cshift_y
1753 , im->stride[2], im->plane[2] );
1756 CalculateTextureSourceRects(source, 3);
1758 glDisable(m_textureTarget);
1761 void CLinuxRendererGLES::DeleteYV12Texture(int index)
1763 YV12Image &im = m_buffers[index].image;
1764 YUVFIELDS &fields = m_buffers[index].fields;
1766 if( fields[FIELD_FULL][0].id == 0 ) return;
1768 /* finish up all textures, and delete them */
1769 g_graphicsContext.BeginPaint(); //FIXME
1770 for(int f = 0;f<MAX_FIELDS;f++)
1772 for(int p = 0;p<MAX_PLANES;p++)
1774 if( fields[f][p].id )
1776 if (glIsTexture(fields[f][p].id))
1777 glDeleteTextures(1, &fields[f][p].id);
1778 fields[f][p].id = 0;
1782 g_graphicsContext.EndPaint();
1784 for(int p = 0;p<MAX_PLANES;p++)
1788 delete[] im.plane[p];
1794 bool CLinuxRendererGLES::CreateYV12Texture(int index)
1796 /* since we also want the field textures, pitch must be texture aligned */
1797 YV12Image &im = m_buffers[index].image;
1798 YUVFIELDS &fields = m_buffers[index].fields;
1800 DeleteYV12Texture(index);
1802 im.height = m_sourceHeight;
1803 im.width = m_sourceWidth;
1807 im.stride[0] = im.width;
1808 im.stride[1] = im.width >> im.cshift_x;
1809 im.stride[2] = im.width >> im.cshift_x;
1811 im.planesize[0] = im.stride[0] * im.height;
1812 im.planesize[1] = im.stride[1] * ( im.height >> im.cshift_y );
1813 im.planesize[2] = im.stride[2] * ( im.height >> im.cshift_y );
1815 for (int i = 0; i < 3; i++)
1816 im.plane[i] = new BYTE[im.planesize[i]];
1818 glEnable(m_textureTarget);
1819 for(int f = 0;f<MAX_FIELDS;f++)
1821 for(int p = 0;p<MAX_PLANES;p++)
1823 if (!glIsTexture(fields[f][p].id))
1825 glGenTextures(1, &fields[f][p].id);
1832 for (int f = FIELD_FULL; f<=FIELD_BOT ; f++)
1834 int fieldshift = (f==FIELD_FULL) ? 0 : 1;
1835 YUVPLANES &planes = fields[f];
1837 planes[0].texwidth = im.width;
1838 planes[0].texheight = im.height >> fieldshift;
1840 if (m_renderMethod & RENDER_SW)
1842 planes[1].texwidth = 0;
1843 planes[1].texheight = 0;
1844 planes[2].texwidth = 0;
1845 planes[2].texheight = 0;
1849 planes[1].texwidth = planes[0].texwidth >> im.cshift_x;
1850 planes[1].texheight = planes[0].texheight >> im.cshift_y;
1851 planes[2].texwidth = planes[0].texwidth >> im.cshift_x;
1852 planes[2].texheight = planes[0].texheight >> im.cshift_y;
1855 if(m_renderMethod & RENDER_POT)
1857 for(int p = 0; p < 3; p++)
1859 planes[p].texwidth = NP2(planes[p].texwidth);
1860 planes[p].texheight = NP2(planes[p].texheight);
1864 for(int p = 0; p < 3; p++)
1866 YUVPLANE &plane = planes[p];
1867 if (plane.texwidth * plane.texheight == 0)
1870 glBindTexture(m_textureTarget, plane.id);
1871 if (m_renderMethod & RENDER_SW)
1873 if(m_renderMethod & RENDER_POT)
1874 CLog::Log(LOGDEBUG, "GL: Creating RGB POT texture of size %d x %d", plane.texwidth, plane.texheight);
1876 CLog::Log(LOGDEBUG, "GL: Creating RGB NPOT texture of size %d x %d", plane.texwidth, plane.texheight);
1878 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
1879 glTexImage2D(m_textureTarget, 0, GL_RGBA, plane.texwidth, plane.texheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1883 if(m_renderMethod & RENDER_POT)
1884 CLog::Log(LOGDEBUG, "GL: Creating YUV POT texture of size %d x %d", plane.texwidth, plane.texheight);
1886 CLog::Log(LOGDEBUG, "GL: Creating YUV NPOT texture of size %d x %d", plane.texwidth, plane.texheight);
1888 glTexImage2D(m_textureTarget, 0, GL_LUMINANCE, plane.texwidth, plane.texheight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
1891 glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1892 glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1893 glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1894 glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1898 glDisable(m_textureTarget);
1902 //********************************************************************************************************
1903 // CoreVideoRef Texture creation, deletion, copying + clearing
1904 //********************************************************************************************************
1905 void CLinuxRendererGLES::UploadCVRefTexture(int index)
1907 #ifdef HAVE_VIDEOTOOLBOXDECODER
1908 CVBufferRef cvBufferRef = m_buffers[index].cvBufferRef;
1912 YUVPLANE &plane = m_buffers[index].fields[0][0];
1914 CVPixelBufferLockBaseAddress(cvBufferRef, kCVPixelBufferLock_ReadOnly);
1915 #if !TARGET_OS_IPHONE
1916 int rowbytes = CVPixelBufferGetBytesPerRow(cvBufferRef);
1918 int bufferWidth = CVPixelBufferGetWidth(cvBufferRef);
1919 int bufferHeight = CVPixelBufferGetHeight(cvBufferRef);
1920 unsigned char *bufferBase = (unsigned char *)CVPixelBufferGetBaseAddress(cvBufferRef);
1922 glEnable(m_textureTarget);
1925 glBindTexture(m_textureTarget, plane.id);
1926 #if !TARGET_OS_IPHONE
1927 #ifdef GL_UNPACK_ROW_LENGTH
1929 glPixelStorei( GL_UNPACK_ROW_LENGTH, rowbytes);
1931 #ifdef GL_TEXTURE_STORAGE_HINT_APPLE
1932 // Set storage hint. Can also use GL_STORAGE_SHARED_APPLE see docs.
1933 glTexParameteri(m_textureTarget, GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_CACHED_APPLE);
1937 // Using BGRA extension to pull in video frame data directly
1938 glTexSubImage2D(m_textureTarget, 0, 0, 0, bufferWidth, bufferHeight, GL_BGRA_EXT, GL_UNSIGNED_BYTE, bufferBase);
1940 #if !TARGET_OS_IPHONE
1941 #ifdef GL_UNPACK_ROW_LENGTH
1943 glPixelStorei( GL_UNPACK_ROW_LENGTH, 0);
1946 glBindTexture(m_textureTarget, 0);
1948 glDisable(m_textureTarget);
1951 CVPixelBufferUnlockBaseAddress(cvBufferRef, kCVPixelBufferLock_ReadOnly);
1952 CVBufferRelease(m_buffers[index].cvBufferRef);
1953 m_buffers[index].cvBufferRef = NULL;
1955 plane.flipindex = m_buffers[index].flipindex;
1959 void CLinuxRendererGLES::DeleteCVRefTexture(int index)
1961 #ifdef HAVE_VIDEOTOOLBOXDECODER
1962 YUVPLANE &plane = m_buffers[index].fields[0][0];
1964 if (m_buffers[index].cvBufferRef)
1965 CVBufferRelease(m_buffers[index].cvBufferRef);
1966 m_buffers[index].cvBufferRef = NULL;
1968 if(plane.id && glIsTexture(plane.id))
1969 glDeleteTextures(1, &plane.id);
1973 bool CLinuxRendererGLES::CreateCVRefTexture(int index)
1975 #ifdef HAVE_VIDEOTOOLBOXDECODER
1976 YV12Image &im = m_buffers[index].image;
1977 YUVFIELDS &fields = m_buffers[index].fields;
1978 YUVPLANE &plane = fields[0][0];
1980 DeleteCVRefTexture(index);
1982 memset(&im , 0, sizeof(im));
1983 memset(&fields, 0, sizeof(fields));
1985 im.height = m_sourceHeight;
1986 im.width = m_sourceWidth;
1988 plane.texwidth = im.width;
1989 plane.texheight = im.height;
1991 if(m_renderMethod & RENDER_POT)
1993 plane.texwidth = NP2(plane.texwidth);
1994 plane.texheight = NP2(plane.texheight);
1996 glEnable(m_textureTarget);
1997 glGenTextures(1, &plane.id);
2000 glBindTexture(m_textureTarget, plane.id);
2001 #if !TARGET_OS_IPHONE
2002 #ifdef GL_UNPACK_ROW_LENGTH
2004 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_sourceWidth);
2006 #ifdef GL_TEXTURE_STORAGE_HINT_APPLE
2007 // Set storage hint. Can also use GL_STORAGE_SHARED_APPLE see docs.
2008 glTexParameteri(m_textureTarget, GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_CACHED_APPLE);
2009 // Set client storage
2011 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
2014 glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2015 glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2016 // This is necessary for non-power-of-two textures
2017 glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2018 glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2019 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
2020 glTexImage2D(m_textureTarget, 0, GL_RGBA, plane.texwidth, plane.texheight, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL);
2022 #if !TARGET_OS_IPHONE
2023 // turn off client storage so it doesn't get picked up for the next texture
2024 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
2026 glBindTexture(m_textureTarget, 0);
2027 glDisable(m_textureTarget);
2032 //********************************************************************************************************
2033 // BYPASS creation, deletion, copying + clearing
2034 //********************************************************************************************************
2035 void CLinuxRendererGLES::UploadBYPASSTexture(int index)
2038 void CLinuxRendererGLES::DeleteBYPASSTexture(int index)
2041 bool CLinuxRendererGLES::CreateBYPASSTexture(int index)
2046 //********************************************************************************************************
2047 // EGLIMG creation, deletion, copying + clearing
2048 //********************************************************************************************************
2049 void CLinuxRendererGLES::UploadEGLIMGTexture(int index)
2051 #ifdef HAS_LIBSTAGEFRIGHT
2052 #ifdef DEBUG_VERBOSE
2053 unsigned int time = XbmcThreads::SystemClockMillis();
2056 if(m_buffers[index].eglimg != EGL_NO_IMAGE_KHR)
2058 YUVPLANE &plane = m_buffers[index].fields[0][0];
2060 glActiveTexture(GL_TEXTURE0);
2061 glBindTexture(m_textureTarget, plane.id);
2062 glEGLImageTargetTexture2DOES(m_textureTarget, (EGLImageKHR)m_buffers[index].eglimg);
2063 glBindTexture(m_textureTarget, 0);
2065 plane.flipindex = m_buffers[index].flipindex;
2068 #ifdef DEBUG_VERBOSE
2069 CLog::Log(LOGDEBUG, "UploadEGLIMGTexture %d: img:%p, tm:%d\n", index, m_buffers[index].eglimg, XbmcThreads::SystemClockMillis() - time);
2073 void CLinuxRendererGLES::DeleteEGLIMGTexture(int index)
2075 #ifdef HAS_LIBSTAGEFRIGHT
2076 YUVPLANE &plane = m_buffers[index].fields[0][0];
2078 if(plane.id && glIsTexture(plane.id))
2079 glDeleteTextures(1, &plane.id);
2083 bool CLinuxRendererGLES::CreateEGLIMGTexture(int index)
2085 #ifdef HAS_LIBSTAGEFRIGHT
2086 YV12Image &im = m_buffers[index].image;
2087 YUVFIELDS &fields = m_buffers[index].fields;
2088 YUVPLANE &plane = fields[0][0];
2090 DeleteEGLIMGTexture(index);
2092 memset(&im , 0, sizeof(im));
2093 memset(&fields, 0, sizeof(fields));
2095 im.height = m_sourceHeight;
2096 im.width = m_sourceWidth;
2098 plane.texwidth = im.width;
2099 plane.texheight = im.height;
2101 if(m_renderMethod & RENDER_POT)
2103 plane.texwidth = NP2(plane.texwidth);
2104 plane.texheight = NP2(plane.texheight);
2106 glEnable(m_textureTarget);
2107 glGenTextures(1, &plane.id);
2110 glBindTexture(m_textureTarget, plane.id);
2112 glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2113 glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2114 // This is necessary for non-power-of-two textures
2115 glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2116 glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2118 glTexImage2D(m_textureTarget, 0, GL_RGBA, plane.texwidth, plane.texheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2120 glDisable(m_textureTarget);
2125 //********************************************************************************************************
2126 // SurfaceTexture creation, deletion, copying + clearing
2127 //********************************************************************************************************
2128 void CLinuxRendererGLES::UploadSurfaceTexture(int index)
2130 #if defined(TARGET_ANDROID)
2131 if (m_buffers[index].mediacodec)
2133 m_buffers[index].fields[0][0].id = m_buffers[index].mediacodec->GetTextureID();
2134 m_buffers[index].mediacodec->ReleaseOutputBuffer(true);
2135 m_buffers[index].mediacodec->UpdateTexImage();
2136 m_buffers[index].mediacodec->GetTransformMatrix(m_textureMatrix);
2137 SAFE_RELEASE(m_buffers[index].mediacodec);
2142 void CLinuxRendererGLES::DeleteSurfaceTexture(int index)
2144 #if defined(TARGET_ANDROID)
2145 SAFE_RELEASE(m_buffers[index].mediacodec);
2148 bool CLinuxRendererGLES::CreateSurfaceTexture(int index)
2153 void CLinuxRendererGLES::SetTextureFilter(GLenum method)
2155 for (int i = 0 ; i<m_NumYV12Buffers ; i++)
2157 YUVFIELDS &fields = m_buffers[i].fields;
2159 for (int f = FIELD_FULL; f<=FIELD_BOT ; f++)
2161 glBindTexture(m_textureTarget, fields[f][0].id);
2162 glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, method);
2163 glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, method);
2166 if (!(m_renderMethod & RENDER_SW))
2168 glBindTexture(m_textureTarget, fields[f][1].id);
2169 glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, method);
2170 glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, method);
2173 glBindTexture(m_textureTarget, fields[f][2].id);
2174 glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, method);
2175 glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, method);
2182 bool CLinuxRendererGLES::Supports(ERENDERFEATURE feature)
2184 // Player controls render, let it dictate available render features
2185 if((m_renderMethod & RENDER_BYPASS))
2187 Features::iterator itr = std::find(m_renderFeatures.begin(),m_renderFeatures.end(), feature);
2188 return itr != m_renderFeatures.end();
2191 if(feature == RENDERFEATURE_BRIGHTNESS)
2194 if(feature == RENDERFEATURE_CONTRAST)
2197 if(feature == RENDERFEATURE_GAMMA)
2200 if(feature == RENDERFEATURE_NOISE)
2203 if(feature == RENDERFEATURE_SHARPNESS)
2206 if (feature == RENDERFEATURE_NONLINSTRETCH)
2209 if (feature == RENDERFEATURE_STRETCH ||
2210 feature == RENDERFEATURE_CROP ||
2211 feature == RENDERFEATURE_ZOOM ||
2212 feature == RENDERFEATURE_VERTICAL_SHIFT ||
2213 feature == RENDERFEATURE_PIXEL_RATIO ||
2214 feature == RENDERFEATURE_POSTPROCESS ||
2215 feature == RENDERFEATURE_ROTATION)
2222 bool CLinuxRendererGLES::SupportsMultiPassRendering()
2227 bool CLinuxRendererGLES::Supports(EDEINTERLACEMODE mode)
2229 // Player controls render, let it dictate available deinterlace modes
2230 if((m_renderMethod & RENDER_BYPASS))
2232 Features::iterator itr = std::find(m_deinterlaceModes.begin(),m_deinterlaceModes.end(), mode);
2233 return itr != m_deinterlaceModes.end();
2236 if (mode == VS_DEINTERLACEMODE_OFF)
2239 if(m_renderMethod & RENDER_OMXEGL)
2242 if(m_renderMethod & RENDER_EGLIMG)
2245 if(m_renderMethod & RENDER_CVREF)
2248 if(mode == VS_DEINTERLACEMODE_AUTO
2249 || mode == VS_DEINTERLACEMODE_FORCE)
2255 bool CLinuxRendererGLES::Supports(EINTERLACEMETHOD method)
2257 // Player controls render, let it dictate available deinterlace methods
2258 if((m_renderMethod & RENDER_BYPASS))
2260 Features::iterator itr = std::find(m_deinterlaceMethods.begin(),m_deinterlaceMethods.end(), method);
2261 return itr != m_deinterlaceMethods.end();
2264 if(m_renderMethod & RENDER_OMXEGL)
2267 if(m_renderMethod & RENDER_EGLIMG)
2270 if(m_renderMethod & RENDER_MEDIACODEC)
2273 if(m_renderMethod & RENDER_CVREF)
2276 if(method == VS_INTERLACEMETHOD_AUTO)
2279 #if defined(__i386__) || defined(__x86_64__)
2280 if(method == VS_INTERLACEMETHOD_DEINTERLACE
2281 || method == VS_INTERLACEMETHOD_DEINTERLACE_HALF
2282 || method == VS_INTERLACEMETHOD_SW_BLEND)
2284 if(method == VS_INTERLACEMETHOD_SW_BLEND)
2291 bool CLinuxRendererGLES::Supports(ESCALINGMETHOD method)
2293 // Player controls render, let it dictate available scaling methods
2294 if((m_renderMethod & RENDER_BYPASS))
2296 Features::iterator itr = std::find(m_scalingMethods.begin(),m_scalingMethods.end(), method);
2297 return itr != m_scalingMethods.end();
2300 if(method == VS_SCALINGMETHOD_NEAREST
2301 || method == VS_SCALINGMETHOD_LINEAR)
2307 EINTERLACEMETHOD CLinuxRendererGLES::AutoInterlaceMethod()
2309 // Player controls render, let it pick the auto-deinterlace method
2310 if((m_renderMethod & RENDER_BYPASS))
2312 if (!m_deinterlaceMethods.empty())
2313 return ((EINTERLACEMETHOD)m_deinterlaceMethods[0]);
2315 return VS_INTERLACEMETHOD_NONE;
2318 if(m_renderMethod & RENDER_OMXEGL)
2319 return VS_INTERLACEMETHOD_NONE;
2321 if(m_renderMethod & RENDER_EGLIMG)
2322 return VS_INTERLACEMETHOD_NONE;
2324 if(m_renderMethod & RENDER_CVREF)
2325 return VS_INTERLACEMETHOD_NONE;
2327 #if defined(__i386__) || defined(__x86_64__)
2328 return VS_INTERLACEMETHOD_DEINTERLACE_HALF;
2330 return VS_INTERLACEMETHOD_SW_BLEND;
2334 unsigned int CLinuxRendererGLES::GetProcessorSize()
2336 if(m_format == RENDER_FMT_OMXEGL
2337 || m_format == RENDER_FMT_CVBREF
2338 || m_format == RENDER_FMT_EGLIMG
2339 || m_format == RENDER_FMT_MEDIACODEC)
2345 #ifdef HAVE_LIBOPENMAX
2346 void CLinuxRendererGLES::AddProcessor(COpenMax* openMax, DVDVideoPicture *picture, int index)
2348 YUVBUFFER &buf = m_buffers[index];
2349 buf.openMaxBuffer = picture->openMaxBuffer;
2352 #ifdef HAVE_VIDEOTOOLBOXDECODER
2353 void CLinuxRendererGLES::AddProcessor(struct __CVBuffer *cvBufferRef, int index)
2355 YUVBUFFER &buf = m_buffers[index];
2356 if (buf.cvBufferRef)
2357 CVBufferRelease(buf.cvBufferRef);
2358 buf.cvBufferRef = cvBufferRef;
2359 // retain another reference, this way dvdplayer and renderer can issue releases.
2360 CVBufferRetain(buf.cvBufferRef);
2363 #ifdef HAS_LIBSTAGEFRIGHT
2364 void CLinuxRendererGLES::AddProcessor(CStageFrightVideo* stf, EGLImageKHR eglimg, int index)
2366 #ifdef DEBUG_VERBOSE
2367 unsigned int time = XbmcThreads::SystemClockMillis();
2370 YUVBUFFER &buf = m_buffers[index];
2371 if (buf.eglimg != EGL_NO_IMAGE_KHR)
2372 stf->ReleaseBuffer(buf.eglimg);
2373 stf->LockBuffer(eglimg);
2376 buf.eglimg = eglimg;
2378 #ifdef DEBUG_VERBOSE
2379 CLog::Log(LOGDEBUG, "AddProcessor %d: img:%p: tm:%d\n", index, eglimg, XbmcThreads::SystemClockMillis() - time);
2384 #if defined(TARGET_ANDROID)
2385 void CLinuxRendererGLES::AddProcessor(CDVDMediaCodecInfo *mediacodec, int index)
2387 #ifdef DEBUG_VERBOSE
2388 unsigned int time = XbmcThreads::SystemClockMillis();
2391 YUVBUFFER &buf = m_buffers[index];
2393 buf.mediacodec = mediacodec->Retain();
2395 #ifdef DEBUG_VERBOSE
2396 CLog::Log(LOGDEBUG, "AddProcessor %d: img:%d: tm:%d\n", index, buf.mediacodec->GetTexture(), XbmcThreads::SystemClockMillis() - time);