0009-new-OpenGL-ES2-video-output-module-for-iOS.patch 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  1. From 57c4882b2ea519e1857a69c382ed892b904b7d03 Mon Sep 17 00:00:00 2001
  2. From: =?UTF-8?q?Felix=20Paul=20K=C3=BChne?= <fkuehne@videolan.org>
  3. Date: Mon, 18 Feb 2013 20:18:01 -0800
  4. Subject: [PATCH 09/10] new OpenGL ES2 video output module for iOS
  5. partially derived from the Mac vout code
  6. ---
  7. configure.ac | 12 +
  8. extras/package/ios/build.sh | 1 +
  9. modules/video_output/Modules.am | 1 +
  10. modules/video_output/ios2.m | 504 ++++++++++++++++++++++++++++++++++++++++
  11. 4 files changed, 518 insertions(+)
  12. create mode 100644 modules/video_output/ios2.m
  13. diff --git a/configure.ac b/configure.ac
  14. index c9666e5..b36390e 100644
  15. --- a/configure.ac
  16. +++ b/configure.ac
  17. @@ -3171,6 +3171,18 @@ then
  18. fi
  19. dnl
  20. +dnl iOS ES2 vout module
  21. +dnl
  22. +AC_ARG_ENABLE(ios-vout2,
  23. + [ --enable-ios-vout2 iOS video output module (default disabled)])
  24. +if test "${enable_ios_vout2}" = "yes"
  25. +then
  26. + VLC_ADD_PLUGIN([vout_ios2])
  27. + VLC_ADD_LIBS([vout_ios2], [-Wl,-framework,OpenGLES,-framework,QuartzCore,-framework,UIKit])
  28. +fi
  29. +
  30. +
  31. +dnl
  32. dnl Windows DirectX module
  33. dnl
  34. diff --git a/extras/package/ios/build.sh b/extras/package/ios/build.sh
  35. index 3b26155..d666ec6 100755
  36. --- a/extras/package/ios/build.sh
  37. +++ b/extras/package/ios/build.sh
  38. @@ -264,6 +264,7 @@ ${VLCROOT}/configure \
  39. --disable-macosx-vlc-app \
  40. --enable-audioqueue \
  41. --enable-ios-vout \
  42. + --enable-ios-vout2 \
  43. --disable-shared \
  44. --disable-macosx-quartztext \
  45. --enable-avcodec \
  46. diff --git a/modules/video_output/Modules.am b/modules/video_output/Modules.am
  47. index aa05454..40be7e7 100644
  48. --- a/modules/video_output/Modules.am
  49. +++ b/modules/video_output/Modules.am
  50. @@ -8,6 +8,7 @@ SOURCES_vmem = vmem.c
  51. SOURCES_yuv = yuv.c
  52. SOURCES_vout_macosx = macosx.m opengl.h opengl.c
  53. SOURCES_vout_ios = ios.m opengl.h opengl.c
  54. +SOURCES_vout_ios2 = ios2.m opengl.h opengl.c
  55. SOURCES_android_surface = androidsurface.c
  56. if HAVE_DECKLINK
  57. diff --git a/modules/video_output/ios2.m b/modules/video_output/ios2.m
  58. new file mode 100644
  59. index 0000000..9238055
  60. --- /dev/null
  61. +++ b/modules/video_output/ios2.m
  62. @@ -0,0 +1,504 @@
  63. +/*****************************************************************************
  64. + * ios2.m: iOS OpenGL ES 2 provider
  65. + *****************************************************************************
  66. + * Copyright (C) 2001-2013 VLC authors and VideoLAN
  67. + * $Id$
  68. + *
  69. + * Authors: Derk-Jan Hartman <hartman at videolan dot org>
  70. + * Eric Petit <titer@m0k.org>
  71. + * Benjamin Pracht <bigben at videolan dot org>
  72. + * Damien Fouilleul <damienf at videolan dot org>
  73. + * Pierre d'Herbemont <pdherbemont at videolan dot org>
  74. + * Felix Paul Kühne <fkuehne at videolan dot org>
  75. + * David Fuhrmann <david dot fuhrmann at googlemail dot com>
  76. + * Rémi Denis-Courmont
  77. + * Juho Vähä-Herttua <juhovh at iki dot fi>
  78. + * Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
  79. + *
  80. + * This program is free software; you can redistribute it and/or modify it
  81. + * under the terms of the GNU Lesser General Public License as published by
  82. + * the Free Software Foundation; either version 2.1 of the License, or
  83. + * (at your option) any later version.
  84. + *
  85. + * This program is distributed in the hope that it will be useful,
  86. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  87. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  88. + * GNU Lesser General Public License for more details.
  89. + *
  90. + * You should have received a copy of the GNU Lesser General Public License
  91. + * along with this program; if not, write to the Free Software Foundation,
  92. + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  93. + *****************************************************************************/
  94. +
  95. +/*****************************************************************************
  96. + * Preamble
  97. + *****************************************************************************/
  98. +
  99. +#import <UIKit/UIKit.h>
  100. +#import <OpenGLES/EAGL.h>
  101. +#import <OpenGLES/ES2/gl.h>
  102. +#import <QuartzCore/QuartzCore.h>
  103. +#import <dlfcn.h>
  104. +
  105. +#ifdef HAVE_CONFIG_H
  106. +# include "config.h"
  107. +#endif
  108. +
  109. +#include <vlc_common.h>
  110. +#include <vlc_plugin.h>
  111. +#include <vlc_vout_display.h>
  112. +#include <vlc_opengl.h>
  113. +#include <vlc_dialog.h>
  114. +#include "opengl.h"
  115. +
  116. +/**
  117. + * Forward declarations
  118. + */
  119. +static int Open (vlc_object_t *);
  120. +static void Close (vlc_object_t *);
  121. +
  122. +static picture_pool_t* PicturePool(vout_display_t *vd, unsigned requested_count);
  123. +static void PictureRender(vout_display_t* vd, picture_t *pic, subpicture_t *subpicture);
  124. +static void PictureDisplay(vout_display_t* vd, picture_t *pic, subpicture_t *subpicture);
  125. +static int Control(vout_display_t* vd, int query, va_list ap);
  126. +
  127. +static void *OurGetProcAddress(vlc_gl_t *, const char *);
  128. +
  129. +static int OpenglESClean(vlc_gl_t* gl);
  130. +static void OpenglESSwap(vlc_gl_t* gl);
  131. +
  132. +/**
  133. + * Module declaration
  134. + */
  135. +vlc_module_begin ()
  136. + set_shortname ("iOS vout")
  137. + set_description (N_("iOS OpenGL video output"))
  138. + set_category (CAT_VIDEO)
  139. + set_subcategory (SUBCAT_VIDEO_VOUT)
  140. + set_capability ("vout display", 300)
  141. + set_callbacks (Open, Close)
  142. +
  143. + add_shortcut ("vout_ios2")
  144. +vlc_module_end ()
  145. +
  146. +@interface VLCOpenGLES2VideoView : UIView
  147. +{
  148. + vout_display_t *_voutDisplay;
  149. + EAGLContext *_eaglContext;
  150. + GLuint _renderBuffer;
  151. + GLuint _frameBuffer;
  152. +
  153. + BOOL _bufferNeedReset;
  154. +}
  155. +@property (readwrite) vout_display_t* voutDisplay;
  156. +@property (readonly) EAGLContext* eaglContext;
  157. +
  158. +- (void)createBuffers;
  159. +- (void)destroyBuffers;
  160. +- (void)resetBuffers;
  161. +
  162. +@end
  163. +
  164. +
  165. +struct vout_display_sys_t
  166. +{
  167. + VLCOpenGLES2VideoView *glESView;
  168. + UIView* viewContainer;
  169. +
  170. + vlc_gl_t gl;
  171. + vout_display_opengl_t *vgl;
  172. +
  173. + picture_pool_t *picturePool;
  174. + picture_t *current;
  175. + bool has_first_frame;
  176. +
  177. + vout_display_place_t place;
  178. +};
  179. +
  180. +
  181. +static void *OurGetProcAddress(vlc_gl_t *gl, const char *name)
  182. +{
  183. + VLC_UNUSED(gl);
  184. +
  185. + return dlsym(RTLD_DEFAULT, name);
  186. +}
  187. +
  188. +static int Open(vlc_object_t *this)
  189. +{
  190. + vout_display_t *vd = (vout_display_t *)this;
  191. + vout_display_sys_t *sys = calloc (1, sizeof(*sys));
  192. + NSAutoreleasePool *autoreleasePool = nil;
  193. +
  194. + if (!sys)
  195. + return VLC_ENOMEM;
  196. +
  197. + vd->sys = sys;
  198. + sys->picturePool = NULL;
  199. + sys->gl.sys = NULL;
  200. +
  201. + autoreleasePool = [[NSAutoreleasePool alloc] init];
  202. +
  203. + /* get the object we will draw into */
  204. + UIView* viewContainer = var_CreateGetAddress (vd, "drawable-nsobject");
  205. + if (!viewContainer || ![viewContainer isKindOfClass:[UIView class]])
  206. + goto bailout;
  207. +
  208. + vout_display_DeleteWindow (vd, NULL);
  209. +
  210. + /* This will be released in Close(), on
  211. + * main thread, after we are done using it. */
  212. + sys->viewContainer = [viewContainer retain];
  213. +
  214. + /* setup the actual OpenGL ES view */
  215. + sys->glESView = [[VLCOpenGLES2VideoView alloc] initWithFrame:[viewContainer bounds]];
  216. +
  217. + if (!sys->glESView)
  218. + goto bailout;
  219. +
  220. + [sys->glESView setVoutDisplay:vd];
  221. +
  222. + [sys->viewContainer performSelectorOnMainThread:@selector(addSubview:) withObject:sys->glESView waitUntilDone:YES];
  223. +
  224. + /* Initialize common OpenGL video display */
  225. + sys->gl.lock = OpenglESClean;
  226. + sys->gl.unlock = nil;
  227. + sys->gl.swap = OpenglESSwap;
  228. + sys->gl.getProcAddress = OurGetProcAddress;
  229. + sys->gl.sys = sys;
  230. + const vlc_fourcc_t *subpicture_chromas;
  231. + video_format_t fmt = vd->fmt;
  232. +
  233. + sys->vgl = vout_display_opengl_New (&vd->fmt, &subpicture_chromas, &sys->gl);
  234. + if (!sys->vgl) {
  235. + sys->gl.sys = NULL;
  236. + goto bailout;
  237. + }
  238. +
  239. + /* */
  240. + vout_display_info_t info = vd->info;
  241. + info.has_pictures_invalid = false;
  242. + info.has_event_thread = true;
  243. + info.subpicture_chromas = subpicture_chromas;
  244. +
  245. + /* Setup vout_display_t once everything is fine */
  246. + vd->info = info;
  247. +
  248. + vd->pool = PicturePool;
  249. + vd->prepare = PictureRender;
  250. + vd->display = PictureDisplay;
  251. + vd->control = Control;
  252. +
  253. + /* */
  254. + [sys->glESView performSelectorOnMainThread:@selector(reshape) withObject:nil waitUntilDone:YES];
  255. +
  256. + [autoreleasePool release];
  257. + return VLC_SUCCESS;
  258. +
  259. +bailout:
  260. + [autoreleasePool release];
  261. + Close(this);
  262. + return VLC_EGENERIC;
  263. +}
  264. +
  265. +void Close (vlc_object_t *this)
  266. +{
  267. + vout_display_t *vd = (vout_display_t *)this;
  268. + vout_display_sys_t *sys = vd->sys;
  269. +
  270. + [sys->glESView setVoutDisplay:nil];
  271. +
  272. + var_Destroy (vd, "drawable-nsobject");
  273. + [sys->viewContainer performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];
  274. + [sys->glESView performSelectorOnMainThread:@selector(removeFromSuperview) withObject:nil waitUntilDone:NO];
  275. +
  276. + if (sys->gl.sys != NULL) {
  277. + msg_Dbg(this, "deleting display");
  278. + vout_display_opengl_Delete(sys->vgl);
  279. + }
  280. +
  281. + [sys->glESView release];
  282. +
  283. + free(sys);
  284. +}
  285. +
  286. +/*****************************************************************************
  287. + * vout display callbacks
  288. + *****************************************************************************/
  289. +
  290. +static int Control(vout_display_t *vd, int query, va_list ap)
  291. +{
  292. + vout_display_sys_t *sys = vd->sys;
  293. +
  294. + switch (query)
  295. + {
  296. + case VOUT_DISPLAY_CHANGE_FULLSCREEN:
  297. + case VOUT_DISPLAY_CHANGE_WINDOW_STATE:
  298. + case VOUT_DISPLAY_HIDE_MOUSE:
  299. + return VLC_SUCCESS;
  300. + case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED:
  301. + case VOUT_DISPLAY_CHANGE_ZOOM:
  302. + case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT:
  303. + case VOUT_DISPLAY_CHANGE_SOURCE_CROP:
  304. + case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE:
  305. + {
  306. + if (!vd->sys)
  307. + return VLC_EGENERIC;
  308. +
  309. + NSAutoreleasePool * autoreleasePool = [[NSAutoreleasePool alloc] init];
  310. +
  311. + const vout_display_cfg_t *cfg;
  312. + const video_format_t *source;
  313. + bool is_forced = false;
  314. +
  315. + if (query == VOUT_DISPLAY_CHANGE_SOURCE_ASPECT || query == VOUT_DISPLAY_CHANGE_SOURCE_CROP) {
  316. + source = (const video_format_t *)va_arg(ap, const video_format_t *);
  317. + cfg = vd->cfg;
  318. + } else {
  319. + source = &vd->source;
  320. + cfg = (const vout_display_cfg_t*)va_arg(ap, const vout_display_cfg_t *);
  321. + if (query == VOUT_DISPLAY_CHANGE_DISPLAY_SIZE)
  322. + is_forced = (bool)va_arg(ap, int);
  323. + }
  324. +
  325. + if (query == VOUT_DISPLAY_CHANGE_DISPLAY_SIZE && is_forced
  326. + && (cfg->display.width != vd->cfg->display.width
  327. + || cfg->display.height != vd->cfg->display.height))
  328. + return VLC_EGENERIC;
  329. +
  330. + /* we always use our current frame here, because we have some size constraints
  331. + in the ui vout provider */
  332. + vout_display_cfg_t cfg_tmp = *cfg;
  333. + CGRect bounds;
  334. + bounds = [sys->glESView bounds];
  335. +
  336. + /* on HiDPI displays, the point bounds don't equal the actual pixel based bounds */
  337. + CGFloat scaleFactor = sys->glESView.contentScaleFactor;
  338. + cfg_tmp.display.width = bounds.size.width * scaleFactor;
  339. + cfg_tmp.display.height = bounds.size.height * scaleFactor;
  340. +
  341. + vout_display_place_t place;
  342. + vout_display_PlacePicture(&place, source, &cfg_tmp, false);
  343. + @synchronized (sys->glESView) {
  344. + sys->place = place;
  345. + }
  346. +
  347. + /* For resize, we call glViewport in reshape and not here.
  348. + This has the positive side effect that we avoid erratic sizing as we animate every resize. */
  349. + if (query != VOUT_DISPLAY_CHANGE_DISPLAY_SIZE)
  350. + // x / y are top left corner, but we need the lower left one
  351. + glViewport(place.x, cfg_tmp.display.height - (place.y + place.height), place.width, place.height);
  352. +
  353. + [autoreleasePool release];
  354. + return VLC_SUCCESS;
  355. + }
  356. +
  357. + case VOUT_DISPLAY_GET_OPENGL:
  358. + {
  359. + vlc_gl_t **gl = va_arg(ap, vlc_gl_t **);
  360. + *gl = &sys->gl;
  361. + return VLC_SUCCESS;
  362. + }
  363. +
  364. + case VOUT_DISPLAY_RESET_PICTURES:
  365. + assert (0);
  366. + default:
  367. + msg_Err(vd, "Unknown request %i in iOS ES 2 vout display", query);
  368. + return VLC_EGENERIC;
  369. + }
  370. +}
  371. +
  372. +static void PictureDisplay(vout_display_t *vd, picture_t *pic, subpicture_t *subpicture)
  373. +{
  374. + sys->has_first_frame = true;
  375. +
  376. + vout_display_sys_t *sys = vd->sys;
  377. + vout_display_opengl_Display(sys->vgl, &vd->source);
  378. +
  379. + picture_Release(pic);
  380. +
  381. + if (subpicture)
  382. + subpicture_Delete(subpicture);
  383. +}
  384. +
  385. +static void PictureRender(vout_display_t *vd, picture_t *pic, subpicture_t *subpicture)
  386. +{
  387. +
  388. + vout_display_sys_t *sys = vd->sys;
  389. +
  390. + vout_display_opengl_Prepare(sys->vgl, pic, subpicture);
  391. +}
  392. +
  393. +static picture_pool_t *PicturePool(vout_display_t *vd, unsigned requested_count)
  394. +{
  395. + vout_display_sys_t *sys = vd->sys;
  396. +
  397. + if (!sys->picturePool)
  398. + sys->picturePool = vout_display_opengl_GetPool(sys->vgl, requested_count);
  399. + assert(sys->picturePool);
  400. + return sys->picturePool;
  401. +}
  402. +
  403. +/*****************************************************************************
  404. + * vout opengl callbacks
  405. + *****************************************************************************/
  406. +static int OpenglESClean(vlc_gl_t *gl)
  407. +{
  408. + vout_display_sys_t *sys = (vout_display_sys_t *)gl->sys;
  409. + [sys->glESView resetBuffers];
  410. + return 0;
  411. +}
  412. +
  413. +static void OpenglESSwap(vlc_gl_t *gl)
  414. +{
  415. + vout_display_sys_t *sys = (vout_display_sys_t *)gl->sys;
  416. + [[sys->glESView eaglContext] presentRenderbuffer:GL_RENDERBUFFER];
  417. +}
  418. +
  419. +/*****************************************************************************
  420. + * Our UIView object
  421. + *****************************************************************************/
  422. +@implementation VLCOpenGLES2VideoView
  423. +@synthesize voutDisplay = _voutDisplay, eaglContext = _eaglContext;
  424. +
  425. ++ (Class)layerClass
  426. +{
  427. + return [CAEAGLLayer class];
  428. +}
  429. +
  430. +- (id)initWithFrame:(CGRect)frame
  431. +{
  432. + self = [super initWithFrame:frame]; // perform selector on main thread?
  433. +
  434. + if (!self)
  435. + return nil;
  436. +
  437. + CAEAGLLayer * layer = (CAEAGLLayer *)self.layer;
  438. + layer.drawableProperties = [NSDictionary dictionaryWithObject:kEAGLColorFormatRGBA8 forKey: kEAGLDrawablePropertyColorFormat];
  439. + layer.opaque = YES;
  440. +
  441. + _eaglContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
  442. + if (!_eaglContext)
  443. + return nil;
  444. + [EAGLContext setCurrentContext:_eaglContext];
  445. +
  446. + [self performSelectorOnMainThread:@selector(createBuffers) withObject:nil waitUntilDone:YES];
  447. + [self performSelectorOnMainThread:@selector(reshape) withObject:nil waitUntilDone:NO];
  448. + [self setAutoresizingMask: UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
  449. +
  450. + return self;
  451. +}
  452. +
  453. +- (void)dealloc
  454. +{
  455. + [_eaglContext release];
  456. + [super dealloc];
  457. +}
  458. +
  459. +/* we don't get the correct scale factor if we don't overwrite this method */
  460. +- (void)drawRect:(CGRect) rect
  461. +{
  462. + [super drawRect:rect];
  463. +}
  464. +
  465. +- (void)createBuffers
  466. +{
  467. + /* make sure the current context is us */
  468. + [EAGLContext setCurrentContext:_eaglContext];
  469. +
  470. + /* create render buffer */
  471. + glGenRenderbuffers(1, &_renderBuffer);
  472. + glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffer);
  473. +
  474. + /* create frame buffer */
  475. + glGenFramebuffers(1, &_frameBuffer);
  476. + glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);
  477. +
  478. + /* allocate storage for the pixels we are going to to draw to */
  479. + [_eaglContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:(id<EAGLDrawable>)self.layer];
  480. +
  481. + /* bind render buffer to frame buffer */
  482. + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _renderBuffer);
  483. +
  484. + /* make sure that our shape is ok */
  485. + [self performSelectorOnMainThread:@selector(reshape) withObject:nil waitUntilDone:NO];
  486. +}
  487. +
  488. +- (void)destroyBuffers
  489. +{
  490. + /* re-set current context */
  491. + [EAGLContext setCurrentContext:_eaglContext];
  492. +
  493. + /* clear frame buffer */
  494. + glDeleteFramebuffers(1, &_frameBuffer);
  495. + _frameBuffer = 0;
  496. +
  497. + /* clear render buffer */
  498. + glDeleteRenderbuffers(1, &_renderBuffer);
  499. + _renderBuffer = 0;
  500. +}
  501. +
  502. +- (void)resetBuffers
  503. +{
  504. + if (_bufferNeedReset) {
  505. + NSLog(@"actually resetting buffers");
  506. + [self destroyBuffers];
  507. + [self createBuffers];
  508. + _bufferNeedReset = NO;
  509. + }
  510. +}
  511. +
  512. +- (void)layoutSubviews
  513. +{
  514. + NSLog(@"layoutSubviews");
  515. + /* this method is called as soon as we are resized.
  516. + * so set a variable to re-create our buffers on the next clean event */
  517. + _bufferNeedReset = YES;
  518. +}
  519. +
  520. +/**
  521. + * Method called by Cocoa when the view is resized.
  522. + */
  523. +- (void)reshape
  524. +{
  525. + assert([[NSThread currentThread] isMainThread]);
  526. +
  527. + CGRect bounds;
  528. + bounds = [self bounds];
  529. +
  530. + vout_display_place_t place;
  531. +
  532. + @synchronized(self) {
  533. + if (_voutDisplay) {
  534. + vout_display_cfg_t cfg_tmp = *(_voutDisplay->cfg);
  535. + CGFloat scaleFactor = self.contentScaleFactor;
  536. +
  537. + cfg_tmp.display.width = bounds.size.width * scaleFactor;
  538. + cfg_tmp.display.height = bounds.size.height * scaleFactor;
  539. +
  540. + vout_display_PlacePicture(&place, &_voutDisplay->source, &cfg_tmp, false);
  541. + _voutDisplay->sys->place = place;
  542. + vout_display_SendEventDisplaySize(_voutDisplay, bounds.size.width * scaleFactor, bounds.size.height * scaleFactor, _voutDisplay->cfg->is_fullscreen);
  543. + }
  544. + }
  545. +
  546. + // x / y are top left corner, but we need the lower left one
  547. + glViewport(place.x, place.y, place.width, place.height);
  548. +}
  549. +
  550. +- (void)updateConstraints
  551. +{
  552. + [self reshape];
  553. + [super updateConstraints];
  554. +}
  555. +
  556. +- (BOOL)isOpaque
  557. +{
  558. + return YES;
  559. +}
  560. +
  561. +- (BOOL)acceptsFirstResponder
  562. +{
  563. + return YES;
  564. +}
  565. +
  566. +@end
  567. --
  568. 1.7.12.4 (Apple Git-37)