2 * Copyright (C) 2007-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
9 #include "RendererVTBGLES.h"
11 #include "../RenderFactory.h"
12 #include "ServiceBroker.h"
13 #include "cores/IPlayer.h"
14 #include "cores/VideoPlayer/DVDCodecs/Video/VTB.h"
15 #include "settings/MediaSettings.h"
16 #include "utils/GLUtils.h"
17 #include "utils/log.h"
18 #if defined(TARGET_DARWIN_IOS)
19 #include "windowing/ios/WinSystemIOS.h"
20 #define WIN_SYSTEM_CLASS CWinSystemIOS
21 #elif defined(TARGET_DARWIN_TVOS)
22 #include "windowing/tvos/WinSystemTVOS.h"
23 #define WIN_SYSTEM_CLASS CWinSystemTVOS
26 #include <CoreVideo/CVBuffer.h>
27 #include <CoreVideo/CVPixelBuffer.h>
28 #include <OpenGLES/ES2/glext.h>
30 CBaseRenderer
* CRendererVTB::Create(CVideoBuffer
*buffer
)
32 VTB::CVideoBufferVTB
*vb
= dynamic_cast<VTB::CVideoBufferVTB
*>(buffer
);
34 return new CRendererVTB();
39 bool CRendererVTB::Register()
41 VIDEOPLAYER::CRendererFactory::RegisterRenderer("vtbgles", CRendererVTB::Create
);
45 CRendererVTB::CRendererVTB()
47 auto winSystem
= dynamic_cast<WIN_SYSTEM_CLASS
*>(CServiceBroker::GetWinSystem());
48 m_glContext
= winSystem
->GetEAGLContextObj();
49 CVReturn ret
= CVOpenGLESTextureCacheCreate(kCFAllocatorDefault
,
54 if (ret
!= kCVReturnSuccess
)
56 CLog::Log(LOGERROR
, "CRendererVTB::CRendererVTB - Error creating texture cache (err: {})", ret
);
59 for (auto &buf
: m_vtbBuffers
)
61 buf
.m_textureY
= nullptr;
62 buf
.m_textureUV
= nullptr;
63 buf
.m_videoBuffer
= nullptr;
64 buf
.m_fence
= nullptr;
68 CRendererVTB::~CRendererVTB()
71 CFRelease(m_textureCache
);
73 for (int i
= 0; i
< NUM_BUFFERS
; ++i
)
79 void CRendererVTB::ReleaseBuffer(int idx
)
81 CPictureBuffer
&buf
= m_buffers
[idx
];
82 CRenderBuffer
&renderBuf
= m_vtbBuffers
[idx
];
85 if (renderBuf
.m_fence
&& glIsSyncAPPLE(renderBuf
.m_fence
))
87 glDeleteSyncAPPLE(renderBuf
.m_fence
);
88 renderBuf
.m_fence
= 0;
90 buf
.videoBuffer
->Release();
91 buf
.videoBuffer
= nullptr;
95 EShaderFormat
CRendererVTB::GetShaderFormat()
100 bool CRendererVTB::LoadShadersHook()
102 CLog::Log(LOGINFO
, "GL: Using CVBREF render method");
103 m_textureTarget
= GL_TEXTURE_2D
;
104 m_renderMethod
= RENDER_CUSTOM
;
108 CLog::Log(LOGINFO
, "CRendererVTB::LoadShadersHook: no texture cache");
112 CVReturn ret
= CVOpenGLESTextureCacheCreate(kCFAllocatorDefault
,
117 if (ret
!= kCVReturnSuccess
)
123 bool CRendererVTB::CreateTexture(int index
)
125 CPictureBuffer
&buf
= m_buffers
[index
];
126 YuvImage
&im
= buf
.image
;
127 CYuvPlane (&planes
)[YuvImage::MAX_PLANES
] = buf
.fields
[0];
129 DeleteTexture(index
);
131 memset(&im
, 0, sizeof(im
));
132 memset(&planes
, 0, sizeof(CYuvPlane
[YuvImage::MAX_PLANES
]));
134 im
.height
= m_sourceHeight
;
135 im
.width
= m_sourceWidth
;
137 planes
[0].texwidth
= im
.width
;
138 planes
[0].texheight
= im
.height
;
139 planes
[1].texwidth
= planes
[0].texwidth
>> im
.cshift_x
;
140 planes
[1].texheight
= planes
[0].texheight
>> im
.cshift_y
;
141 planes
[2].texwidth
= planes
[1].texwidth
;
142 planes
[2].texheight
= planes
[1].texheight
;
144 for (int p
= 0; p
< 3; p
++)
146 planes
[p
].pixpertex_x
= 1;
147 planes
[p
].pixpertex_y
= 1;
154 void CRendererVTB::DeleteTexture(int index
)
156 CRenderBuffer
&renderBuf
= m_vtbBuffers
[index
];
157 CYuvPlane (&planes
)[YuvImage::MAX_PLANES
] = m_buffers
[index
].fields
[0];
159 if (renderBuf
.m_textureY
)
160 CFRelease(renderBuf
.m_textureY
);
161 renderBuf
.m_textureY
= nullptr;
163 if (renderBuf
.m_textureUV
)
164 CFRelease(renderBuf
.m_textureUV
);
165 renderBuf
.m_textureUV
= nullptr;
167 ReleaseBuffer(index
);
174 bool CRendererVTB::UploadTexture(int index
)
176 CRenderBuffer
&renderBuf
= m_vtbBuffers
[index
];
177 CPictureBuffer
&buf
= m_buffers
[index
];
178 CYuvPlane (&planes
)[YuvImage::MAX_PLANES
] = m_buffers
[index
].fields
[0];
179 YuvImage
&im
= m_buffers
[index
].image
;
181 VTB::CVideoBufferVTB
*vb
= dynamic_cast<VTB::CVideoBufferVTB
*>(buf
.videoBuffer
);
187 CVOpenGLESTextureCacheFlush(m_textureCache
, 0);
189 if (renderBuf
.m_textureY
)
190 CFRelease(renderBuf
.m_textureY
);
191 renderBuf
.m_textureY
= nullptr;
193 if (renderBuf
.m_textureUV
)
194 CFRelease(renderBuf
.m_textureUV
);
195 renderBuf
.m_textureUV
= nullptr;
198 ret
= CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault
,
200 vb
->GetPB(), nullptr, GL_TEXTURE_2D
, GL_LUMINANCE
,
201 im
.width
, im
.height
, GL_LUMINANCE
, GL_UNSIGNED_BYTE
,
203 &renderBuf
.m_textureY
);
205 if (ret
!= kCVReturnSuccess
)
207 CLog::Log(LOGERROR
, "CRendererVTB::UploadTexture - Error uploading texture Y (err: {})", ret
);
211 ret
= CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault
,
213 vb
->GetPB(), nullptr, GL_TEXTURE_2D
, GL_LUMINANCE_ALPHA
,
214 im
.width
/2, im
.height
/2, GL_LUMINANCE_ALPHA
, GL_UNSIGNED_BYTE
,
216 &renderBuf
.m_textureUV
);
218 if (ret
!= kCVReturnSuccess
)
220 CLog::Log(LOGERROR
, "CRendererVTB::UploadTexture - Error uploading texture UV (err: {})", ret
);
225 planes
[0].id
= CVOpenGLESTextureGetName(renderBuf
.m_textureY
);
226 planes
[1].id
= CVOpenGLESTextureGetName(renderBuf
.m_textureUV
);
227 planes
[2].id
= CVOpenGLESTextureGetName(renderBuf
.m_textureUV
);
229 for (int p
=0; p
<2; p
++)
231 glBindTexture(m_textureTarget
, planes
[p
].id
);
232 glTexParameteri(m_textureTarget
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
233 glTexParameteri(m_textureTarget
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
234 glTexParameteri(m_textureTarget
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
235 glTexParameteri(m_textureTarget
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
237 glBindTexture(m_textureTarget
, 0);
241 CalculateTextureSourceRects(index
, 3);
245 void CRendererVTB::AfterRenderHook(int idx
)
247 CRenderBuffer
&renderBuf
= m_vtbBuffers
[idx
];
248 if (renderBuf
.m_fence
&& glIsSyncAPPLE(renderBuf
.m_fence
))
250 glDeleteSyncAPPLE(renderBuf
.m_fence
);
252 renderBuf
.m_fence
= glFenceSyncAPPLE(GL_SYNC_GPU_COMMANDS_COMPLETE_APPLE
, 0);
255 bool CRendererVTB::NeedBuffer(int idx
)
257 CRenderBuffer
&renderBuf
= m_vtbBuffers
[idx
];
258 if (renderBuf
.m_fence
&& glIsSyncAPPLE(renderBuf
.m_fence
))
260 int syncState
= GL_UNSIGNALED_APPLE
;
261 glGetSyncivAPPLE(renderBuf
.m_fence
, GL_SYNC_STATUS_APPLE
, 1, nullptr, &syncState
);
262 if (syncState
!= GL_SIGNALED_APPLE
)