1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
|
#define GL_ALPHA_TEST 0x0bc0
#include "opengl/opengl.hpp"
struct VideoCGL;
@interface RubyVideoCGL : NSOpenGLView {
@public
VideoCGL* video;
}
-(id) initWith:(VideoCGL*)video pixelFormat:(NSOpenGLPixelFormat*)pixelFormat;
-(void) reshape;
@end
struct VideoCGL : Video, OpenGL {
VideoCGL() { initialize(); }
~VideoCGL() { terminate(); }
auto ready() -> bool { return _ready; }
auto context() -> uintptr { return (uintptr)_context; }
auto blocking() -> bool { return _blocking; }
auto smooth() -> bool { return _smooth; }
auto shader() -> string { return _shader; }
auto setContext(uintptr context) -> bool {
if(_context == (NSView*)context) return true;
_context = (NSView*)context;
return initialize();
}
auto setBlocking(bool blocking) -> bool {
if(_blocking == blocking) return true;
_blocking = blocking;
if(!view) return true;
@autoreleasepool {
[[view openGLContext] makeCurrentContext];
int blocking = _blocking;
[[view openGLContext] setValues:&blocking forParameter:NSOpenGLCPSwapInterval];
}
return true;
}
auto setSmooth(bool smooth) -> bool {
if(_smooth == smooth) return true;
_smooth = smooth;
if(!_shader) OpenGL::filter = _smooth ? GL_LINEAR : GL_NEAREST;
return true;
}
auto setShader(string shader) -> bool {
if(_shader == shader) return true;
OpenGL::shader(_shader = shader);
if(!_shader) OpenGL::filter = _smooth ? GL_LINEAR : GL_NEAREST;
return true;
}
auto clear() -> void {
if(!ready()) return;
@autoreleasepool {
[view lockFocus];
OpenGL::clear();
[[view openGLContext] flushBuffer];
[view unlockFocus];
}
}
auto lock(uint32_t*& data, uint& pitch, uint width, uint height) -> bool {
if(!ready()) return false;
OpenGL::size(width, height);
return OpenGL::lock(data, pitch);
}
auto unlock() -> void {
if(!ready()) return;
}
auto output() -> void {
if(!ready()) return;
@autoreleasepool {
if([view lockFocusIfCanDraw]) {
auto area = [view convertRectToBacking:[view bounds]];
OpenGL::outputWidth = area.size.width;
OpenGL::outputHeight = area.size.height;
OpenGL::output();
[[view openGLContext] flushBuffer];
[view unlockFocus];
}
}
}
private:
auto initialize() -> bool {
terminate();
if(!_context) return false;
@autoreleasepool {
NSOpenGLPixelFormatAttribute attributeList[] = {
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
NSOpenGLPFAColorSize, 24,
NSOpenGLPFAAlphaSize, 8,
NSOpenGLPFADoubleBuffer,
0
};
auto size = [_context frame].size;
auto format = [[[NSOpenGLPixelFormat alloc] initWithAttributes:attributeList] autorelease];
auto context = [[[NSOpenGLContext alloc] initWithFormat:format shareContext:nil] autorelease];
view = [[RubyVideoCGL alloc] initWith:this pixelFormat:format];
[view setOpenGLContext:context];
[view setFrame:NSMakeRect(0, 0, size.width, size.height)];
[view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
[view setWantsBestResolutionOpenGLSurface:YES];
[_context addSubview:view];
[context setView:view];
[view lockFocus];
OpenGL::initialize();
int blocking = _blocking;
[[view openGLContext] setValues:&blocking forParameter:NSOpenGLCPSwapInterval];
[view unlockFocus];
}
clear();
return _ready = true;
}
auto terminate() -> void {
_ready = false;
OpenGL::terminate();
if(!view) return;
@autoreleasepool {
[view removeFromSuperview];
[view release];
view = nil;
}
}
RubyVideoCGL* view = nullptr;
bool _ready = false;
NSView* _context = nullptr;
bool _blocking = false;
bool _smooth = true;
string _shader;
};
@implementation RubyVideoCGL : NSOpenGLView
-(id) initWith:(VideoCGL*)videoPointer pixelFormat:(NSOpenGLPixelFormat*)pixelFormat {
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0) pixelFormat:pixelFormat]) {
video = videoPointer;
}
return self;
}
-(void) reshape {
video->output();
}
@end
|