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 ;
6 SPECIALIZED-ARRAY: float
9 UNION: ?rect rect POSTPONE: f ;
10 UNION: ?float float POSTPONE: f ;
13 { rect rect read-only } ;
14 C: <viewport-state> viewport-state
17 { rect ?rect read-only } ;
18 C: <scissor-state> scissor-state
20 TUPLE: multisample-state
21 { multisample? boolean read-only }
22 { sample-alpha-to-coverage? boolean read-only }
23 { sample-alpha-to-one? boolean read-only }
24 { sample-coverage ?float read-only }
25 { invert-sample-coverage? boolean read-only } ;
26 C: <multisample-state> multisample-state
30 cmp-less cmp-less-equal cmp-equal
31 cmp-greater-equal cmp-greater cmp-not-equal ;
36 op-inc-wrap op-dec-wrap ;
38 UNION: ?comparison comparison POSTPONE: f ;
41 { value integer initial: 0 read-only }
42 { mask integer initial: HEX: FFFFFFFF read-only }
43 { comparison comparison initial: cmp-always read-only }
44 { stencil-fail-op stencil-op initial: op-keep read-only }
45 { depth-fail-op stencil-op initial: op-keep read-only }
46 { depth-pass-op stencil-op initial: op-keep read-only } ;
47 C: <stencil-mode> stencil-mode
49 UNION: ?stencil-mode stencil-mode POSTPONE: f ;
52 { front-mode ?stencil-mode initial: f read-only }
53 { back-mode ?stencil-mode initial: f read-only } ;
54 C: <stencil-state> stencil-state
56 TUPLE: depth-range-state
57 { near float initial: 0.0 read-only }
58 { far float initial: 1.0 read-only } ;
59 C: <depth-range-state> depth-range-state
62 { comparison ?comparison initial: f read-only } ;
63 C: <depth-state> depth-state
65 VARIANT: blend-equation
66 eq-add eq-subtract eq-reverse-subtract eq-min eq-max ;
67 VARIANT: blend-function
69 func-source func-one-minus-source
70 func-dest func-one-minus-dest
71 func-constant func-one-minus-constant
72 func-source-alpha func-one-minus-source-alpha
73 func-dest-alpha func-one-minus-dest-alpha
74 func-constant-alpha func-one-minus-constant-alpha ;
76 VARIANT: source-only-blend-function
77 func-source-alpha-saturate ;
79 UNION: source-blend-function blend-function source-only-blend-function ;
82 { equation blend-equation initial: eq-add read-only }
83 { source-function source-blend-function initial: func-source-alpha read-only }
84 { dest-function blend-function initial: func-one-minus-source-alpha read-only } ;
85 C: <blend-mode> blend-mode
87 UNION: ?blend-mode blend-mode POSTPONE: f ;
90 { constant-color sequence initial: f read-only }
91 { rgb-mode ?blend-mode read-only }
92 { alpha-mode ?blend-mode read-only } ;
93 C: <blend-state> blend-state
96 { color sequence initial: { t t t t } read-only }
97 { depth boolean initial: t read-only }
98 { stencil-front integer initial: HEX: FFFFFFFF read-only }
99 { stencil-back integer initial: HEX: FFFFFFFF read-only } ;
100 C: <mask-state> mask-state
102 VARIANT: triangle-face
104 VARIANT: triangle-cull
105 cull-front cull-back cull-all ;
106 VARIANT: triangle-mode
107 triangle-points triangle-lines triangle-fill ;
109 UNION: ?triangle-cull triangle-cull POSTPONE: f ;
111 TUPLE: triangle-cull-state
112 { front-face triangle-face initial: face-ccw read-only }
113 { cull ?triangle-cull initial: f read-only } ;
114 C: <triangle-cull-state> triangle-cull-state
116 TUPLE: triangle-state
117 { front-mode triangle-mode initial: triangle-fill read-only }
118 { back-mode triangle-mode initial: triangle-fill read-only }
119 { antialias? boolean initial: f read-only } ;
120 C: <triangle-state> triangle-state
122 VARIANT: point-sprite-origin
123 origin-upper-left origin-lower-left ;
126 { size ?float initial: 1.0 read-only }
127 { sprite-origin point-sprite-origin initial: origin-upper-left read-only }
128 { fade-threshold float initial: 1.0 read-only } ;
129 C: <point-state> point-state
132 { width float initial: 1.0 read-only }
133 { antialias? boolean initial: f read-only } ;
134 C: <line-state> line-state
152 : gl-triangle-face ( triangle-face -- face )
154 { face-ccw [ GL_CCW ] }
155 { face-cw [ GL_CW ] }
158 : gl-triangle-face> ( triangle-face -- face )
160 { $ GL_CCW [ face-ccw ] }
161 { $ GL_CW [ face-cw ] }
164 : gl-triangle-cull ( triangle-cull -- cull )
166 { cull-front [ GL_FRONT ] }
167 { cull-back [ GL_BACK ] }
168 { cull-all [ GL_FRONT_AND_BACK ] }
171 : gl-triangle-cull> ( triangle-cull -- cull )
173 { $ GL_FRONT [ cull-front ] }
174 { $ GL_BACK [ cull-back ] }
175 { $ GL_FRONT_AND_BACK [ cull-all ] }
178 : gl-triangle-mode ( triangle-mode -- mode )
180 { triangle-points [ GL_POINT ] }
181 { triangle-lines [ GL_LINE ] }
182 { triangle-fill [ GL_FILL ] }
185 : gl-triangle-mode> ( triangle-mode -- mode )
187 { $ GL_POINT [ triangle-points ] }
188 { $ GL_LINE [ triangle-lines ] }
189 { $ GL_FILL [ triangle-fill ] }
192 : gl-point-sprite-origin ( point-sprite-origin -- sprite-origin )
194 { origin-upper-left [ GL_UPPER_LEFT ] }
195 { origin-lower-left [ GL_LOWER_LEFT ] }
198 : gl-point-sprite-origin> ( point-sprite-origin -- sprite-origin )
200 { $ GL_UPPER_LEFT [ origin-upper-left ] }
201 { $ GL_LOWER_LEFT [ origin-lower-left ] }
204 : gl-comparison ( comparison -- comparison )
206 { cmp-never [ GL_NEVER ] }
207 { cmp-always [ GL_ALWAYS ] }
208 { cmp-less [ GL_LESS ] }
209 { cmp-less-equal [ GL_LEQUAL ] }
210 { cmp-equal [ GL_EQUAL ] }
211 { cmp-greater-equal [ GL_GEQUAL ] }
212 { cmp-greater [ GL_GREATER ] }
213 { cmp-not-equal [ GL_NOTEQUAL ] }
216 : gl-comparison> ( comparison -- comparison )
218 { $ GL_NEVER [ cmp-never ] }
219 { $ GL_ALWAYS [ cmp-always ] }
220 { $ GL_LESS [ cmp-less ] }
221 { $ GL_LEQUAL [ cmp-less-equal ] }
222 { $ GL_EQUAL [ cmp-equal ] }
223 { $ GL_GEQUAL [ cmp-greater-equal ] }
224 { $ GL_GREATER [ cmp-greater ] }
225 { $ GL_NOTEQUAL [ cmp-not-equal ] }
228 : gl-stencil-op ( stencil-op -- op )
230 { op-keep [ GL_KEEP ] }
231 { op-zero [ GL_ZERO ] }
232 { op-replace [ GL_REPLACE ] }
233 { op-invert [ GL_INVERT ] }
234 { op-inc-sat [ GL_INCR ] }
235 { op-dec-sat [ GL_DECR ] }
236 { op-inc-wrap [ GL_INCR_WRAP ] }
237 { op-dec-wrap [ GL_DECR_WRAP ] }
240 : gl-stencil-op> ( op -- op )
242 { $ GL_KEEP [ op-keep ] }
243 { $ GL_ZERO [ op-zero ] }
244 { $ GL_REPLACE [ op-replace ] }
245 { $ GL_INVERT [ op-invert ] }
246 { $ GL_INCR [ op-inc-sat ] }
247 { $ GL_DECR [ op-dec-sat ] }
248 { $ GL_INCR_WRAP [ op-inc-wrap ] }
249 { $ GL_DECR_WRAP [ op-dec-wrap ] }
252 : (set-stencil-mode) ( gl-face stencil-mode -- )
254 [ [ comparison>> gl-comparison ] [ value>> ] [ mask>> ] tri glStencilFuncSeparate ]
256 [ stencil-fail-op>> ] [ depth-fail-op>> ] [ depth-pass-op>> ] tri
257 [ gl-stencil-op ] tri@ glStencilOpSeparate
261 : gl-blend-equation ( blend-equation -- blend-equation )
263 { eq-add [ GL_FUNC_ADD ] }
264 { eq-subtract [ GL_FUNC_SUBTRACT ] }
265 { eq-reverse-subtract [ GL_FUNC_REVERSE_SUBTRACT ] }
266 { eq-min [ GL_MIN ] }
267 { eq-max [ GL_MAX ] }
270 : gl-blend-equation> ( blend-equation -- blend-equation )
272 { $ GL_FUNC_ADD [ eq-add ] }
273 { $ GL_FUNC_SUBTRACT [ eq-subtract ] }
274 { $ GL_FUNC_REVERSE_SUBTRACT [ eq-reverse-subtract ] }
275 { $ GL_MIN [ eq-min ] }
276 { $ GL_MAX [ eq-max ] }
279 : gl-blend-function ( blend-function -- blend-function )
281 { func-zero [ GL_ZERO ] }
282 { func-one [ GL_ONE ] }
283 { func-source [ GL_SRC_COLOR ] }
284 { func-one-minus-source [ GL_ONE_MINUS_SRC_COLOR ] }
285 { func-dest [ GL_DST_COLOR ] }
286 { func-one-minus-dest [ GL_ONE_MINUS_DST_COLOR ] }
287 { func-constant [ GL_CONSTANT_COLOR ] }
288 { func-one-minus-constant [ GL_ONE_MINUS_CONSTANT_COLOR ] }
289 { func-source-alpha [ GL_SRC_ALPHA ] }
290 { func-one-minus-source-alpha [ GL_ONE_MINUS_SRC_ALPHA ] }
291 { func-dest-alpha [ GL_DST_ALPHA ] }
292 { func-one-minus-dest-alpha [ GL_ONE_MINUS_DST_ALPHA ] }
293 { func-constant-alpha [ GL_CONSTANT_ALPHA ] }
294 { func-one-minus-constant-alpha [ GL_ONE_MINUS_CONSTANT_ALPHA ] }
295 { func-source-alpha-saturate [ GL_SRC_ALPHA_SATURATE ] }
298 : gl-blend-function> ( blend-function -- blend-function )
300 { $ GL_ZERO [ func-zero ] }
301 { $ GL_ONE [ func-one ] }
302 { $ GL_SRC_COLOR [ func-source ] }
303 { $ GL_ONE_MINUS_SRC_COLOR [ func-one-minus-source ] }
304 { $ GL_DST_COLOR [ func-dest ] }
305 { $ GL_ONE_MINUS_DST_COLOR [ func-one-minus-dest ] }
306 { $ GL_CONSTANT_COLOR [ func-constant ] }
307 { $ GL_ONE_MINUS_CONSTANT_COLOR [ func-one-minus-constant ] }
308 { $ GL_SRC_ALPHA [ func-source-alpha ] }
309 { $ GL_ONE_MINUS_SRC_ALPHA [ func-one-minus-source-alpha ] }
310 { $ GL_DST_ALPHA [ func-dest-alpha ] }
311 { $ GL_ONE_MINUS_DST_ALPHA [ func-one-minus-dest-alpha ] }
312 { $ GL_CONSTANT_ALPHA [ func-constant-alpha ] }
313 { $ GL_ONE_MINUS_CONSTANT_ALPHA [ func-one-minus-constant-alpha ] }
314 { $ GL_SRC_ALPHA_SATURATE [ func-source-alpha-saturate ] }
319 GENERIC: set-gpu-state* ( state -- )
321 M: viewport-state set-gpu-state*
322 rect>> [ loc>> first2 ] [ dim>> first2 ] bi glViewport ;
324 M: triangle-cull-state set-gpu-state*
326 [ front-face>> gl-triangle-face glFrontFace ]
327 [ GL_CULL_FACE swap cull>> [ gl-triangle-cull glCullFace glEnable ] [ glDisable ] if* ]
330 M: triangle-state set-gpu-state*
332 [ GL_FRONT swap front-mode>> gl-triangle-mode glPolygonMode ]
333 [ GL_BACK swap back-mode>> gl-triangle-mode glPolygonMode ]
334 [ GL_POLYGON_SMOOTH swap antialias?>> [ glEnable ] [ glDisable ] if ]
337 M: point-state set-gpu-state*
339 [ GL_VERTEX_PROGRAM_POINT_SIZE swap size>> [ glPointSize glDisable ] [ glEnable ] if* ]
340 [ GL_POINT_SPRITE_COORD_ORIGIN swap sprite-origin>> gl-point-sprite-origin glPointParameteri ]
341 [ GL_POINT_FADE_THRESHOLD_SIZE swap fade-threshold>> glPointParameterf ]
344 M: line-state set-gpu-state*
346 [ width>> glLineWidth ]
347 [ GL_LINE_SMOOTH swap antialias?>> [ glEnable ] [ glDisable ] if ]
350 M: scissor-state set-gpu-state*
351 GL_SCISSOR_TEST swap rect>>
352 [ [ loc>> first2 ] [ dim>> first2 ] bi glViewport glEnable ]
355 M: multisample-state set-gpu-state*
357 GL_MULTISAMPLE glEnable
359 [ GL_SAMPLE_ALPHA_TO_COVERAGE swap sample-alpha-to-coverage?>>
360 [ glEnable ] [ glDisable ] if
362 [ GL_SAMPLE_ALPHA_TO_ONE swap sample-alpha-to-one?>>
363 [ glEnable ] [ glDisable ] if
365 [ GL_SAMPLE_COVERAGE swap [ invert-sample-coverage?>> >c-bool ] [ sample-coverage>> ] bi
366 [ swap glSampleCoverage glEnable ] [ drop glDisable ] if*
369 ] [ drop GL_MULTISAMPLE glDisable ] if ;
371 M: stencil-state set-gpu-state*
372 [ ] [ front-mode>> ] [ back-mode>> ] tri or
374 GL_STENCIL_TEST glEnable
375 [ front-mode>> GL_FRONT swap (set-stencil-mode) ]
376 [ back-mode>> GL_BACK swap (set-stencil-mode) ] bi
377 ] [ drop GL_STENCIL_TEST glDisable ] if ;
379 M: depth-range-state set-gpu-state*
380 [ near>> ] [ far>> ] bi glDepthRange ;
382 M: depth-state set-gpu-state*
383 GL_DEPTH_TEST swap comparison>> [ gl-comparison glDepthFunc glEnable ] [ glDisable ] if* ;
385 M: blend-state set-gpu-state*
386 [ ] [ rgb-mode>> ] [ alpha-mode>> ] tri or
389 [ constant-color>> [ first4 glBlendColor ] when* ]
391 [ rgb-mode>> ] [ alpha-mode>> ] bi {
392 [ [ equation>> gl-blend-equation ] bi@ glBlendEquationSeparate ]
395 [ source-function>> gl-blend-function ]
396 [ dest-function>> gl-blend-function ] bi
397 ] bi@ glBlendFuncSeparate
401 ] [ drop GL_BLEND glDisable ] if ;
403 M: mask-state set-gpu-state*
405 [ color>> [ >c-bool ] map first4 glColorMask ]
406 [ depth>> >c-bool glDepthMask ]
407 [ GL_FRONT swap stencil-front>> glStencilMaskSeparate ]
408 [ GL_BACK swap stencil-back>> glStencilMaskSeparate ]
411 : set-gpu-state ( states -- )
413 [ [ set-gpu-state* ] each ]
414 [ set-gpu-state* ] if ; inline
418 : get-gl-bool ( enum -- value )
419 0 <uchar> [ glGetBooleanv ] keep *uchar c-bool> ;
420 : get-gl-int ( enum -- value )
421 0 <int> [ glGetIntegerv ] keep *int ;
422 : get-gl-float ( enum -- value )
423 0 <float> [ glGetFloatv ] keep *float ;
425 : get-gl-bools ( enum count -- value )
426 <byte-array> [ glGetBooleanv ] keep [ c-bool> ] { } map-as ;
427 : get-gl-ints ( enum count -- value )
428 <int-array> [ glGetIntegerv ] keep ;
429 : get-gl-floats ( enum count -- value )
430 <float-array> [ glGetFloatv ] keep ;
432 : get-gl-rect ( enum -- value )
433 4 get-gl-ints first4 [ 2array ] 2bi@ <rect> ;
435 : gl-enabled? ( enum -- ? )
436 glIsEnabled c-bool> ;
440 : get-viewport-state ( -- viewport-state )
441 GL_VIEWPORT get-gl-rect <viewport-state> ;
443 : get-scissor-state ( -- scissor-state )
444 GL_SCISSOR_TEST get-gl-bool
445 [ GL_SCISSOR_BOX get-gl-rect ] [ f ] if
448 : get-multisample-state ( -- multisample-state )
449 GL_MULTISAMPLE gl-enabled?
450 GL_SAMPLE_ALPHA_TO_COVERAGE gl-enabled?
451 GL_SAMPLE_ALPHA_TO_ONE gl-enabled?
452 GL_SAMPLE_COVERAGE gl-enabled? [
453 GL_SAMPLE_COVERAGE_VALUE get-gl-float
454 GL_SAMPLE_COVERAGE_INVERT get-gl-bool
456 <multisample-state> ;
458 : get-stencil-state ( -- stencil-state )
459 GL_STENCIL_TEST gl-enabled? [
460 GL_STENCIL_REF get-gl-int
461 GL_STENCIL_VALUE_MASK get-gl-int
462 GL_STENCIL_FUNC get-gl-int gl-comparison>
463 GL_STENCIL_FAIL get-gl-int gl-stencil-op>
464 GL_STENCIL_PASS_DEPTH_FAIL get-gl-int gl-stencil-op>
465 GL_STENCIL_PASS_DEPTH_PASS get-gl-int gl-stencil-op>
468 GL_STENCIL_BACK_REF get-gl-int
469 GL_STENCIL_BACK_VALUE_MASK get-gl-int
470 GL_STENCIL_BACK_FUNC get-gl-int gl-comparison>
471 GL_STENCIL_BACK_FAIL get-gl-int gl-stencil-op>
472 GL_STENCIL_BACK_PASS_DEPTH_FAIL get-gl-int gl-stencil-op>
473 GL_STENCIL_BACK_PASS_DEPTH_PASS get-gl-int gl-stencil-op>
478 : get-depth-range-state ( -- depth-range-state )
479 GL_DEPTH_RANGE 2 get-gl-floats first2 <depth-range-state> ;
481 : get-depth-state ( -- depth-state )
482 GL_DEPTH_TEST gl-enabled?
483 [ GL_DEPTH_FUNC get-gl-int gl-comparison> ] [ f ] if
486 : get-blend-state ( -- blend-state )
487 GL_BLEND gl-enabled? [
488 GL_BLEND_COLOR 4 get-gl-floats
490 GL_BLEND_EQUATION_RGB get-gl-int gl-blend-equation>
491 GL_BLEND_SRC_RGB get-gl-int gl-blend-function>
492 GL_BLEND_DST_RGB get-gl-int gl-blend-function>
495 GL_BLEND_EQUATION_ALPHA get-gl-int gl-blend-equation>
496 GL_BLEND_SRC_ALPHA get-gl-int gl-blend-function>
497 GL_BLEND_DST_ALPHA get-gl-int gl-blend-function>
502 : get-mask-state ( -- mask-state )
503 GL_COLOR_WRITEMASK 4 get-gl-bools
504 GL_DEPTH_WRITEMASK get-gl-bool
505 GL_STENCIL_WRITEMASK get-gl-int
506 GL_STENCIL_BACK_WRITEMASK get-gl-int
509 : get-triangle-cull-state ( -- triangle-cull-state )
510 GL_FRONT_FACE get-gl-int gl-triangle-face>
511 GL_CULL_FACE gl-enabled?
512 [ GL_CULL_FACE_MODE get-gl-int gl-triangle-cull> ]
514 <triangle-cull-state> ;
516 : get-triangle-state ( -- triangle-state )
517 GL_POLYGON_MODE 2 get-gl-ints
518 first2 [ gl-triangle-mode> ] bi@
519 GL_POLYGON_SMOOTH gl-enabled?
522 : get-point-state ( -- point-state )
523 GL_VERTEX_PROGRAM_POINT_SIZE gl-enabled?
524 [ f ] [ GL_POINT_SIZE get-gl-float ] if
525 GL_POINT_SPRITE_COORD_ORIGIN get-gl-int gl-point-sprite-origin>
526 GL_POINT_FADE_THRESHOLD_SIZE get-gl-float
529 : get-line-state ( -- line-state )
530 GL_LINE_WIDTH get-gl-float
531 GL_LINE_SMOOTH gl-enabled?