1 ! (c)2009 Joe Groff bsd license
2 USING: accessors alien.c-types arrays byte-arrays combinators gpu
3 kernel literals math math.rectangles opengl opengl.gl sequences
4 variants specialized-arrays.int specialized-arrays.float ;
7 UNION: ?rect rect POSTPONE: f ;
8 UNION: ?float float POSTPONE: f ;
11 { rect rect read-only } ;
12 C: <viewport-state> viewport-state
15 { rect ?rect read-only } ;
16 C: <scissor-state> scissor-state
18 TUPLE: multisample-state
19 { multisample? boolean read-only }
20 { sample-alpha-to-coverage? boolean read-only }
21 { sample-alpha-to-one? boolean read-only }
22 { sample-coverage ?float read-only }
23 { invert-sample-coverage? boolean read-only } ;
24 C: <multisample-state> multisample-state
28 cmp-less cmp-less-equal cmp-equal
29 cmp-greater-equal cmp-greater cmp-not-equal ;
34 op-inc-wrap op-dec-wrap ;
36 UNION: ?comparison comparison POSTPONE: f ;
39 { value integer initial: 0 read-only }
40 { mask integer initial: HEX: FFFFFFFF read-only }
41 { comparison comparison initial: cmp-always read-only }
42 { stencil-fail-op stencil-op initial: op-keep read-only }
43 { depth-fail-op stencil-op initial: op-keep read-only }
44 { depth-pass-op stencil-op initial: op-keep read-only } ;
45 C: <stencil-mode> stencil-mode
47 UNION: ?stencil-mode stencil-mode POSTPONE: f ;
50 { front-mode ?stencil-mode initial: f read-only }
51 { back-mode ?stencil-mode initial: f read-only } ;
52 C: <stencil-state> stencil-state
54 TUPLE: depth-range-state
55 { near float initial: 0.0 read-only }
56 { far float initial: 1.0 read-only } ;
57 C: <depth-range-state> depth-range-state
60 { comparison ?comparison initial: f read-only } ;
61 C: <depth-state> depth-state
63 VARIANT: blend-equation
64 eq-add eq-subtract eq-reverse-subtract eq-min eq-max ;
65 VARIANT: blend-function
67 func-source func-one-minus-source
68 func-dest func-one-minus-dest
69 func-constant func-one-minus-constant
70 func-source-alpha func-one-minus-source-alpha
71 func-dest-alpha func-one-minus-dest-alpha
72 func-constant-alpha func-one-minus-constant-alpha ;
74 VARIANT: source-only-blend-function
75 func-source-alpha-saturate ;
77 UNION: source-blend-function blend-function source-only-blend-function ;
80 { equation blend-equation initial: eq-add read-only }
81 { source-function source-blend-function initial: func-source-alpha read-only }
82 { dest-function blend-function initial: func-one-minus-source-alpha read-only } ;
83 C: <blend-mode> blend-mode
85 UNION: ?blend-mode blend-mode POSTPONE: f ;
88 { constant-color sequence initial: f read-only }
89 { rgb-mode ?blend-mode read-only }
90 { alpha-mode ?blend-mode read-only } ;
91 C: <blend-state> blend-state
94 { color sequence initial: { t t t t } read-only }
95 { depth boolean initial: t read-only }
96 { stencil-front integer initial: HEX: FFFFFFFF read-only }
97 { stencil-back integer initial: HEX: FFFFFFFF read-only } ;
98 C: <mask-state> mask-state
100 VARIANT: triangle-face
102 VARIANT: triangle-cull
103 cull-front cull-back cull-all ;
104 VARIANT: triangle-mode
105 triangle-points triangle-lines triangle-fill ;
107 UNION: ?triangle-cull triangle-cull POSTPONE: f ;
109 TUPLE: triangle-cull-state
110 { front-face triangle-face initial: face-ccw read-only }
111 { cull ?triangle-cull initial: f read-only } ;
112 C: <triangle-cull-state> triangle-cull-state
114 TUPLE: triangle-state
115 { front-mode triangle-mode initial: triangle-fill read-only }
116 { back-mode triangle-mode initial: triangle-fill read-only }
117 { antialias? boolean initial: f read-only } ;
118 C: <triangle-state> triangle-state
120 VARIANT: point-sprite-origin
121 origin-upper-left origin-lower-left ;
124 { size ?float initial: 1.0 read-only }
125 { sprite-origin point-sprite-origin initial: origin-upper-left read-only }
126 { fade-threshold float initial: 1.0 read-only } ;
127 C: <point-state> point-state
130 { width float initial: 1.0 read-only }
131 { antialias? boolean initial: f read-only } ;
132 C: <line-state> line-state
150 : gl-triangle-face ( triangle-face -- face )
152 { face-ccw [ GL_CCW ] }
153 { face-cw [ GL_CW ] }
156 : gl-triangle-face> ( triangle-face -- face )
158 { $ GL_CCW [ face-ccw ] }
159 { $ GL_CW [ face-cw ] }
162 : gl-triangle-cull ( triangle-cull -- cull )
164 { cull-front [ GL_FRONT ] }
165 { cull-back [ GL_BACK ] }
166 { cull-all [ GL_FRONT_AND_BACK ] }
169 : gl-triangle-cull> ( triangle-cull -- cull )
171 { $ GL_FRONT [ cull-front ] }
172 { $ GL_BACK [ cull-back ] }
173 { $ GL_FRONT_AND_BACK [ cull-all ] }
176 : gl-triangle-mode ( triangle-mode -- mode )
178 { triangle-points [ GL_POINT ] }
179 { triangle-lines [ GL_LINE ] }
180 { triangle-fill [ GL_FILL ] }
183 : gl-triangle-mode> ( triangle-mode -- mode )
185 { $ GL_POINT [ triangle-points ] }
186 { $ GL_LINE [ triangle-lines ] }
187 { $ GL_FILL [ triangle-fill ] }
190 : gl-point-sprite-origin ( point-sprite-origin -- sprite-origin )
192 { origin-upper-left [ GL_UPPER_LEFT ] }
193 { origin-lower-left [ GL_LOWER_LEFT ] }
196 : gl-point-sprite-origin> ( point-sprite-origin -- sprite-origin )
198 { $ GL_UPPER_LEFT [ origin-upper-left ] }
199 { $ GL_LOWER_LEFT [ origin-lower-left ] }
202 : gl-comparison ( comparison -- comparison )
204 { cmp-never [ GL_NEVER ] }
205 { cmp-always [ GL_ALWAYS ] }
206 { cmp-less [ GL_LESS ] }
207 { cmp-less-equal [ GL_LEQUAL ] }
208 { cmp-equal [ GL_EQUAL ] }
209 { cmp-greater-equal [ GL_GEQUAL ] }
210 { cmp-greater [ GL_GREATER ] }
211 { cmp-not-equal [ GL_NOTEQUAL ] }
214 : gl-comparison> ( comparison -- comparison )
216 { $ GL_NEVER [ cmp-never ] }
217 { $ GL_ALWAYS [ cmp-always ] }
218 { $ GL_LESS [ cmp-less ] }
219 { $ GL_LEQUAL [ cmp-less-equal ] }
220 { $ GL_EQUAL [ cmp-equal ] }
221 { $ GL_GEQUAL [ cmp-greater-equal ] }
222 { $ GL_GREATER [ cmp-greater ] }
223 { $ GL_NOTEQUAL [ cmp-not-equal ] }
226 : gl-stencil-op ( stencil-op -- op )
228 { op-keep [ GL_KEEP ] }
229 { op-zero [ GL_ZERO ] }
230 { op-replace [ GL_REPLACE ] }
231 { op-invert [ GL_INVERT ] }
232 { op-inc-sat [ GL_INCR ] }
233 { op-dec-sat [ GL_DECR ] }
234 { op-inc-wrap [ GL_INCR_WRAP ] }
235 { op-dec-wrap [ GL_DECR_WRAP ] }
238 : gl-stencil-op> ( op -- op )
240 { $ GL_KEEP [ op-keep ] }
241 { $ GL_ZERO [ op-zero ] }
242 { $ GL_REPLACE [ op-replace ] }
243 { $ GL_INVERT [ op-invert ] }
244 { $ GL_INCR [ op-inc-sat ] }
245 { $ GL_DECR [ op-dec-sat ] }
246 { $ GL_INCR_WRAP [ op-inc-wrap ] }
247 { $ GL_DECR_WRAP [ op-dec-wrap ] }
250 : (set-stencil-mode) ( gl-face stencil-mode -- )
252 [ [ comparison>> gl-comparison ] [ value>> ] [ mask>> ] tri glStencilFuncSeparate ]
254 [ stencil-fail-op>> ] [ depth-fail-op>> ] [ depth-pass-op>> ] tri
255 [ gl-stencil-op ] tri@ glStencilOpSeparate
259 : gl-blend-equation ( blend-equation -- blend-equation )
261 { eq-add [ GL_FUNC_ADD ] }
262 { eq-subtract [ GL_FUNC_SUBTRACT ] }
263 { eq-reverse-subtract [ GL_FUNC_REVERSE_SUBTRACT ] }
264 { eq-min [ GL_MIN ] }
265 { eq-max [ GL_MAX ] }
268 : gl-blend-equation> ( blend-equation -- blend-equation )
270 { $ GL_FUNC_ADD [ eq-add ] }
271 { $ GL_FUNC_SUBTRACT [ eq-subtract ] }
272 { $ GL_FUNC_REVERSE_SUBTRACT [ eq-reverse-subtract ] }
273 { $ GL_MIN [ eq-min ] }
274 { $ GL_MAX [ eq-max ] }
277 : gl-blend-function ( blend-function -- blend-function )
279 { func-zero [ GL_ZERO ] }
280 { func-one [ GL_ONE ] }
281 { func-source [ GL_SRC_COLOR ] }
282 { func-one-minus-source [ GL_ONE_MINUS_SRC_COLOR ] }
283 { func-dest [ GL_DST_COLOR ] }
284 { func-one-minus-dest [ GL_ONE_MINUS_DST_COLOR ] }
285 { func-constant [ GL_CONSTANT_COLOR ] }
286 { func-one-minus-constant [ GL_ONE_MINUS_CONSTANT_COLOR ] }
287 { func-source-alpha [ GL_SRC_ALPHA ] }
288 { func-one-minus-source-alpha [ GL_ONE_MINUS_SRC_ALPHA ] }
289 { func-dest-alpha [ GL_DST_ALPHA ] }
290 { func-one-minus-dest-alpha [ GL_ONE_MINUS_DST_ALPHA ] }
291 { func-constant-alpha [ GL_CONSTANT_ALPHA ] }
292 { func-one-minus-constant-alpha [ GL_ONE_MINUS_CONSTANT_ALPHA ] }
293 { func-source-alpha-saturate [ GL_SRC_ALPHA_SATURATE ] }
296 : gl-blend-function> ( blend-function -- blend-function )
298 { $ GL_ZERO [ func-zero ] }
299 { $ GL_ONE [ func-one ] }
300 { $ GL_SRC_COLOR [ func-source ] }
301 { $ GL_ONE_MINUS_SRC_COLOR [ func-one-minus-source ] }
302 { $ GL_DST_COLOR [ func-dest ] }
303 { $ GL_ONE_MINUS_DST_COLOR [ func-one-minus-dest ] }
304 { $ GL_CONSTANT_COLOR [ func-constant ] }
305 { $ GL_ONE_MINUS_CONSTANT_COLOR [ func-one-minus-constant ] }
306 { $ GL_SRC_ALPHA [ func-source-alpha ] }
307 { $ GL_ONE_MINUS_SRC_ALPHA [ func-one-minus-source-alpha ] }
308 { $ GL_DST_ALPHA [ func-dest-alpha ] }
309 { $ GL_ONE_MINUS_DST_ALPHA [ func-one-minus-dest-alpha ] }
310 { $ GL_CONSTANT_ALPHA [ func-constant-alpha ] }
311 { $ GL_ONE_MINUS_CONSTANT_ALPHA [ func-one-minus-constant-alpha ] }
312 { $ GL_SRC_ALPHA_SATURATE [ func-source-alpha-saturate ] }
317 GENERIC: set-gpu-state* ( state -- )
319 M: viewport-state set-gpu-state*
320 rect>> [ loc>> first2 ] [ dim>> first2 ] bi glViewport ;
322 M: triangle-cull-state set-gpu-state*
324 [ front-face>> gl-triangle-face glFrontFace ]
325 [ GL_CULL_FACE swap cull>> [ gl-triangle-cull glCullFace glEnable ] [ glDisable ] if* ]
328 M: triangle-state set-gpu-state*
330 [ GL_FRONT swap front-mode>> gl-triangle-mode glPolygonMode ]
331 [ GL_BACK swap back-mode>> gl-triangle-mode glPolygonMode ]
332 [ GL_POLYGON_SMOOTH swap antialias?>> [ glEnable ] [ glDisable ] if ]
335 M: point-state set-gpu-state*
337 [ GL_VERTEX_PROGRAM_POINT_SIZE swap size>> [ glPointSize glDisable ] [ glEnable ] if* ]
338 [ GL_POINT_SPRITE_COORD_ORIGIN swap sprite-origin>> gl-point-sprite-origin glPointParameteri ]
339 [ GL_POINT_FADE_THRESHOLD_SIZE swap fade-threshold>> glPointParameterf ]
342 M: line-state set-gpu-state*
344 [ width>> glLineWidth ]
345 [ GL_LINE_SMOOTH swap antialias?>> [ glEnable ] [ glDisable ] if ]
348 M: scissor-state set-gpu-state*
349 GL_SCISSOR_TEST swap rect>>
350 [ [ loc>> first2 ] [ dim>> first2 ] bi glViewport glEnable ]
353 M: multisample-state set-gpu-state*
355 GL_MULTISAMPLE glEnable
357 [ GL_SAMPLE_ALPHA_TO_COVERAGE swap sample-alpha-to-coverage?>>
358 [ glEnable ] [ glDisable ] if
360 [ GL_SAMPLE_ALPHA_TO_ONE swap sample-alpha-to-one?>>
361 [ glEnable ] [ glDisable ] if
363 [ GL_SAMPLE_COVERAGE swap [ invert-sample-coverage?>> >c-bool ] [ sample-coverage>> ] bi
364 [ swap glSampleCoverage glEnable ] [ drop glDisable ] if*
367 ] [ drop GL_MULTISAMPLE glDisable ] if ;
369 M: stencil-state set-gpu-state*
370 [ ] [ front-mode>> ] [ back-mode>> ] tri or
372 GL_STENCIL_TEST glEnable
373 [ front-mode>> GL_FRONT swap (set-stencil-mode) ]
374 [ back-mode>> GL_BACK swap (set-stencil-mode) ] bi
375 ] [ drop GL_STENCIL_TEST glDisable ] if ;
377 M: depth-range-state set-gpu-state*
378 [ near>> ] [ far>> ] bi glDepthRange ;
380 M: depth-state set-gpu-state*
381 GL_DEPTH_TEST swap comparison>> [ gl-comparison glDepthFunc glEnable ] [ glDisable ] if* ;
383 M: blend-state set-gpu-state*
384 [ ] [ rgb-mode>> ] [ alpha-mode>> ] tri or
387 [ constant-color>> [ first4 glBlendColor ] when* ]
389 [ rgb-mode>> ] [ alpha-mode>> ] bi {
390 [ [ equation>> gl-blend-equation ] bi@ glBlendEquationSeparate ]
393 [ source-function>> gl-blend-function ]
394 [ dest-function>> gl-blend-function ] bi
395 ] bi@ glBlendFuncSeparate
399 ] [ drop GL_BLEND glDisable ] if ;
401 M: mask-state set-gpu-state*
403 [ color>> [ >c-bool ] map first4 glColorMask ]
404 [ depth>> >c-bool glDepthMask ]
405 [ GL_FRONT swap stencil-front>> glStencilMaskSeparate ]
406 [ GL_BACK swap stencil-back>> glStencilMaskSeparate ]
409 : set-gpu-state ( states -- )
411 [ [ set-gpu-state* ] each ]
412 [ set-gpu-state* ] if ; inline
416 : get-gl-bool ( enum -- value )
417 0 <uchar> [ glGetBooleanv ] keep *uchar c-bool> ;
418 : get-gl-int ( enum -- value )
419 0 <int> [ glGetIntegerv ] keep *int ;
420 : get-gl-float ( enum -- value )
421 0 <float> [ glGetFloatv ] keep *float ;
423 : get-gl-bools ( enum count -- value )
424 <byte-array> [ glGetBooleanv ] keep [ c-bool> ] { } map-as ;
425 : get-gl-ints ( enum count -- value )
426 <int-array> [ glGetIntegerv ] keep ;
427 : get-gl-floats ( enum count -- value )
428 <float-array> [ glGetFloatv ] keep ;
430 : get-gl-rect ( enum -- value )
431 4 get-gl-ints first4 [ 2array ] 2bi@ <rect> ;
433 : gl-enabled? ( enum -- ? )
434 glIsEnabled c-bool> ;
438 : get-viewport-state ( -- viewport-state )
439 GL_VIEWPORT get-gl-rect <viewport-state> ;
441 : get-scissor-state ( -- scissor-state )
442 GL_SCISSOR_TEST get-gl-bool
443 [ GL_SCISSOR_BOX get-gl-rect ] [ f ] if
446 : get-multisample-state ( -- multisample-state )
447 GL_MULTISAMPLE gl-enabled?
448 GL_SAMPLE_ALPHA_TO_COVERAGE gl-enabled?
449 GL_SAMPLE_ALPHA_TO_ONE gl-enabled?
450 GL_SAMPLE_COVERAGE gl-enabled? [
451 GL_SAMPLE_COVERAGE_VALUE get-gl-float
452 GL_SAMPLE_COVERAGE_INVERT get-gl-bool
454 <multisample-state> ;
456 : get-stencil-state ( -- stencil-state )
457 GL_STENCIL_TEST gl-enabled? [
458 GL_STENCIL_REF get-gl-int
459 GL_STENCIL_VALUE_MASK get-gl-int
460 GL_STENCIL_FUNC get-gl-int gl-comparison>
461 GL_STENCIL_FAIL get-gl-int gl-stencil-op>
462 GL_STENCIL_PASS_DEPTH_FAIL get-gl-int gl-stencil-op>
463 GL_STENCIL_PASS_DEPTH_PASS get-gl-int gl-stencil-op>
466 GL_STENCIL_BACK_REF get-gl-int
467 GL_STENCIL_BACK_VALUE_MASK get-gl-int
468 GL_STENCIL_BACK_FUNC get-gl-int gl-comparison>
469 GL_STENCIL_BACK_FAIL get-gl-int gl-stencil-op>
470 GL_STENCIL_BACK_PASS_DEPTH_FAIL get-gl-int gl-stencil-op>
471 GL_STENCIL_BACK_PASS_DEPTH_PASS get-gl-int gl-stencil-op>
476 : get-depth-range-state ( -- depth-range-state )
477 GL_DEPTH_RANGE 2 get-gl-floats first2 <depth-range-state> ;
479 : get-depth-state ( -- depth-state )
480 GL_DEPTH_TEST gl-enabled?
481 [ GL_DEPTH_FUNC get-gl-int gl-comparison> ] [ f ] if
484 : get-blend-state ( -- blend-state )
485 GL_BLEND gl-enabled? [
486 GL_BLEND_COLOR 4 get-gl-floats
488 GL_BLEND_EQUATION_RGB get-gl-int gl-blend-equation>
489 GL_BLEND_SRC_RGB get-gl-int gl-blend-function>
490 GL_BLEND_DST_RGB get-gl-int gl-blend-function>
493 GL_BLEND_EQUATION_ALPHA get-gl-int gl-blend-equation>
494 GL_BLEND_SRC_ALPHA get-gl-int gl-blend-function>
495 GL_BLEND_DST_ALPHA get-gl-int gl-blend-function>
500 : get-mask-state ( -- mask-state )
501 GL_COLOR_WRITEMASK 4 get-gl-bools
502 GL_DEPTH_WRITEMASK get-gl-bool
503 GL_STENCIL_WRITEMASK get-gl-int
504 GL_STENCIL_BACK_WRITEMASK get-gl-int
507 : get-triangle-cull-state ( -- triangle-cull-state )
508 GL_FRONT_FACE get-gl-int gl-triangle-face>
509 GL_CULL_FACE gl-enabled?
510 [ GL_CULL_FACE_MODE get-gl-int gl-triangle-cull> ]
512 <triangle-cull-state> ;
514 : get-triangle-state ( -- triangle-state )
515 GL_POLYGON_MODE 2 get-gl-ints
516 first2 [ gl-triangle-mode> ] bi@
517 GL_POLYGON_SMOOTH gl-enabled?
520 : get-point-state ( -- point-state )
521 GL_VERTEX_PROGRAM_POINT_SIZE gl-enabled?
522 [ f ] [ GL_POINT_SIZE get-gl-float ] if
523 GL_POINT_SPRITE_COORD_ORIGIN get-gl-int gl-point-sprite-origin>
524 GL_POINT_FADE_THRESHOLD_SIZE get-gl-float
527 : get-line-state ( -- line-state )
528 GL_LINE_WIDTH get-gl-float
529 GL_LINE_SMOOTH gl-enabled?