File: cgl.cpp

package info (click to toggle)
higan 106-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster
  • size: 9,640 kB
  • sloc: cpp: 108,736; ansic: 809; makefile: 22; sh: 7
file content (165 lines) | stat: -rw-r--r-- 4,211 bytes parent folder | download
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