1 ! Copyright (C) 2009 Joe Groff.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors alien.c-types alien.data arrays byte-arrays
4 combinators gpu kernel literals math math.rectangles opengl
5 opengl.gl sequences typed variants specialized-arrays ;
6 QUALIFIED-WITH: alien.c-types c
8 SPECIALIZED-ARRAY: c:int
9 SPECIALIZED-ARRAY: c:float
13 { rect rect read-only } ;
14 C: <viewport-state> viewport-state
17 { rect maybe{ 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 maybe{ 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 ;
39 { value integer initial: 0 read-only }
40 { mask integer initial: 0xFFFFFFFF 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
48 { front-mode maybe{ stencil-mode } initial: f read-only }
49 { back-mode maybe{ stencil-mode } initial: f read-only } ;
50 C: <stencil-state> stencil-state
52 TUPLE: depth-range-state
53 { near float initial: 0.0 read-only }
54 { far float initial: 1.0 read-only } ;
55 C: <depth-range-state> depth-range-state
58 { comparison maybe{ comparison } initial: f read-only } ;
59 C: <depth-state> depth-state
61 VARIANT: blend-equation
62 eq-add eq-subtract eq-reverse-subtract eq-min eq-max ;
63 VARIANT: blend-function
65 func-source func-one-minus-source
66 func-dest func-one-minus-dest
67 func-constant func-one-minus-constant
68 func-source-alpha func-one-minus-source-alpha
69 func-dest-alpha func-one-minus-dest-alpha
70 func-constant-alpha func-one-minus-constant-alpha ;
72 VARIANT: source-only-blend-function
73 func-source-alpha-saturate ;
75 UNION: source-blend-function blend-function source-only-blend-function ;
78 { equation blend-equation initial: eq-add read-only }
79 { source-function source-blend-function initial: func-source-alpha read-only }
80 { dest-function blend-function initial: func-one-minus-source-alpha read-only } ;
81 C: <blend-mode> blend-mode
84 { constant-color sequence initial: f read-only }
85 { rgb-mode maybe{ blend-mode } read-only }
86 { alpha-mode maybe{ blend-mode } read-only } ;
87 C: <blend-state> blend-state
90 { color sequence initial: { t t t t } read-only }
91 { depth boolean initial: t read-only }
92 { stencil-front integer initial: 0xFFFFFFFF read-only }
93 { stencil-back integer initial: 0xFFFFFFFF read-only } ;
94 C: <mask-state> mask-state
96 VARIANT: triangle-face
98 VARIANT: triangle-cull
99 cull-front cull-back cull-all ;
100 VARIANT: triangle-mode
101 triangle-points triangle-lines triangle-fill ;
103 TUPLE: triangle-cull-state
104 { front-face triangle-face initial: face-ccw read-only }
105 { cull maybe{ triangle-cull } initial: f read-only } ;
106 C: <triangle-cull-state> triangle-cull-state
108 TUPLE: triangle-state
109 { front-mode triangle-mode initial: triangle-fill read-only }
110 { back-mode triangle-mode initial: triangle-fill read-only }
111 { antialias? boolean initial: f read-only } ;
112 C: <triangle-state> triangle-state
114 VARIANT: point-sprite-origin
115 origin-upper-left origin-lower-left ;
118 { size maybe{ float } initial: 1.0 read-only }
119 { sprite-origin point-sprite-origin initial: origin-upper-left read-only }
120 { fade-threshold float initial: 1.0 read-only } ;
121 C: <point-state> point-state
124 { width float initial: 1.0 read-only }
125 { antialias? boolean initial: f read-only } ;
126 C: <line-state> line-state
144 : gl-triangle-face ( triangle-face -- face )
146 { face-ccw [ GL_CCW ] }
147 { face-cw [ GL_CW ] }
150 : gl-triangle-face> ( triangle-face -- face )
152 { $ GL_CCW [ face-ccw ] }
153 { $ GL_CW [ face-cw ] }
156 : gl-triangle-cull ( triangle-cull -- cull )
158 { cull-front [ GL_FRONT ] }
159 { cull-back [ GL_BACK ] }
160 { cull-all [ GL_FRONT_AND_BACK ] }
163 : gl-triangle-cull> ( triangle-cull -- cull )
165 { $ GL_FRONT [ cull-front ] }
166 { $ GL_BACK [ cull-back ] }
167 { $ GL_FRONT_AND_BACK [ cull-all ] }
170 : gl-triangle-mode ( triangle-mode -- mode )
172 { triangle-points [ GL_POINT ] }
173 { triangle-lines [ GL_LINE ] }
174 { triangle-fill [ GL_FILL ] }
177 : gl-triangle-mode> ( triangle-mode -- mode )
179 { $ GL_POINT [ triangle-points ] }
180 { $ GL_LINE [ triangle-lines ] }
181 { $ GL_FILL [ triangle-fill ] }
184 : gl-point-sprite-origin ( point-sprite-origin -- sprite-origin )
186 { origin-upper-left [ GL_UPPER_LEFT ] }
187 { origin-lower-left [ GL_LOWER_LEFT ] }
190 : gl-point-sprite-origin> ( point-sprite-origin -- sprite-origin )
192 { $ GL_UPPER_LEFT [ origin-upper-left ] }
193 { $ GL_LOWER_LEFT [ origin-lower-left ] }
196 : gl-comparison ( comparison -- comparison )
198 { cmp-never [ GL_NEVER ] }
199 { cmp-always [ GL_ALWAYS ] }
200 { cmp-less [ GL_LESS ] }
201 { cmp-less-equal [ GL_LEQUAL ] }
202 { cmp-equal [ GL_EQUAL ] }
203 { cmp-greater-equal [ GL_GEQUAL ] }
204 { cmp-greater [ GL_GREATER ] }
205 { cmp-not-equal [ GL_NOTEQUAL ] }
208 : gl-comparison> ( comparison -- comparison )
210 { $ GL_NEVER [ cmp-never ] }
211 { $ GL_ALWAYS [ cmp-always ] }
212 { $ GL_LESS [ cmp-less ] }
213 { $ GL_LEQUAL [ cmp-less-equal ] }
214 { $ GL_EQUAL [ cmp-equal ] }
215 { $ GL_GEQUAL [ cmp-greater-equal ] }
216 { $ GL_GREATER [ cmp-greater ] }
217 { $ GL_NOTEQUAL [ cmp-not-equal ] }
220 : gl-stencil-op ( stencil-op -- op )
222 { op-keep [ GL_KEEP ] }
223 { op-zero [ GL_ZERO ] }
224 { op-replace [ GL_REPLACE ] }
225 { op-invert [ GL_INVERT ] }
226 { op-inc-sat [ GL_INCR ] }
227 { op-dec-sat [ GL_DECR ] }
228 { op-inc-wrap [ GL_INCR_WRAP ] }
229 { op-dec-wrap [ GL_DECR_WRAP ] }
232 : gl-stencil-op> ( op -- op )
234 { $ GL_KEEP [ op-keep ] }
235 { $ GL_ZERO [ op-zero ] }
236 { $ GL_REPLACE [ op-replace ] }
237 { $ GL_INVERT [ op-invert ] }
238 { $ GL_INCR [ op-inc-sat ] }
239 { $ GL_DECR [ op-dec-sat ] }
240 { $ GL_INCR_WRAP [ op-inc-wrap ] }
241 { $ GL_DECR_WRAP [ op-dec-wrap ] }
244 : (set-stencil-mode) ( gl-face stencil-mode -- )
246 [ [ comparison>> gl-comparison ] [ value>> ] [ mask>> ] tri glStencilFuncSeparate ]
248 [ stencil-fail-op>> ] [ depth-fail-op>> ] [ depth-pass-op>> ] tri
249 [ gl-stencil-op ] tri@ glStencilOpSeparate
253 : gl-blend-equation ( blend-equation -- blend-equation )
255 { eq-add [ GL_FUNC_ADD ] }
256 { eq-subtract [ GL_FUNC_SUBTRACT ] }
257 { eq-reverse-subtract [ GL_FUNC_REVERSE_SUBTRACT ] }
258 { eq-min [ GL_MIN ] }
259 { eq-max [ GL_MAX ] }
262 : gl-blend-equation> ( blend-equation -- blend-equation )
264 { $ GL_FUNC_ADD [ eq-add ] }
265 { $ GL_FUNC_SUBTRACT [ eq-subtract ] }
266 { $ GL_FUNC_REVERSE_SUBTRACT [ eq-reverse-subtract ] }
267 { $ GL_MIN [ eq-min ] }
268 { $ GL_MAX [ eq-max ] }
271 : gl-blend-function ( blend-function -- blend-function )
273 { func-zero [ GL_ZERO ] }
274 { func-one [ GL_ONE ] }
275 { func-source [ GL_SRC_COLOR ] }
276 { func-one-minus-source [ GL_ONE_MINUS_SRC_COLOR ] }
277 { func-dest [ GL_DST_COLOR ] }
278 { func-one-minus-dest [ GL_ONE_MINUS_DST_COLOR ] }
279 { func-constant [ GL_CONSTANT_COLOR ] }
280 { func-one-minus-constant [ GL_ONE_MINUS_CONSTANT_COLOR ] }
281 { func-source-alpha [ GL_SRC_ALPHA ] }
282 { func-one-minus-source-alpha [ GL_ONE_MINUS_SRC_ALPHA ] }
283 { func-dest-alpha [ GL_DST_ALPHA ] }
284 { func-one-minus-dest-alpha [ GL_ONE_MINUS_DST_ALPHA ] }
285 { func-constant-alpha [ GL_CONSTANT_ALPHA ] }
286 { func-one-minus-constant-alpha [ GL_ONE_MINUS_CONSTANT_ALPHA ] }
287 { func-source-alpha-saturate [ GL_SRC_ALPHA_SATURATE ] }
290 : gl-blend-function> ( blend-function -- blend-function )
292 { $ GL_ZERO [ func-zero ] }
293 { $ GL_ONE [ func-one ] }
294 { $ GL_SRC_COLOR [ func-source ] }
295 { $ GL_ONE_MINUS_SRC_COLOR [ func-one-minus-source ] }
296 { $ GL_DST_COLOR [ func-dest ] }
297 { $ GL_ONE_MINUS_DST_COLOR [ func-one-minus-dest ] }
298 { $ GL_CONSTANT_COLOR [ func-constant ] }
299 { $ GL_ONE_MINUS_CONSTANT_COLOR [ func-one-minus-constant ] }
300 { $ GL_SRC_ALPHA [ func-source-alpha ] }
301 { $ GL_ONE_MINUS_SRC_ALPHA [ func-one-minus-source-alpha ] }
302 { $ GL_DST_ALPHA [ func-dest-alpha ] }
303 { $ GL_ONE_MINUS_DST_ALPHA [ func-one-minus-dest-alpha ] }
304 { $ GL_CONSTANT_ALPHA [ func-constant-alpha ] }
305 { $ GL_ONE_MINUS_CONSTANT_ALPHA [ func-one-minus-constant-alpha ] }
306 { $ GL_SRC_ALPHA_SATURATE [ func-source-alpha-saturate ] }
311 GENERIC: set-gpu-state* ( state -- )
313 M: viewport-state set-gpu-state*
314 rect>> [ loc>> ] [ dim>> ] bi gl-viewport ;
316 M: triangle-cull-state set-gpu-state*
318 [ front-face>> gl-triangle-face glFrontFace ]
319 [ GL_CULL_FACE swap cull>> [ gl-triangle-cull glCullFace glEnable ] [ glDisable ] if* ]
322 M: triangle-state set-gpu-state*
324 [ GL_FRONT swap front-mode>> gl-triangle-mode glPolygonMode ]
325 [ GL_BACK swap back-mode>> gl-triangle-mode glPolygonMode ]
326 [ GL_POLYGON_SMOOTH swap antialias?>> [ glEnable ] [ glDisable ] if ]
329 M: point-state set-gpu-state*
331 [ GL_VERTEX_PROGRAM_POINT_SIZE swap size>> [ glPointSize glDisable ] [ glEnable ] if* ]
332 [ GL_POINT_SPRITE_COORD_ORIGIN swap sprite-origin>> gl-point-sprite-origin glPointParameteri ]
333 [ GL_POINT_FADE_THRESHOLD_SIZE swap fade-threshold>> glPointParameterf ]
336 M: line-state set-gpu-state*
338 [ width>> glLineWidth ]
339 [ GL_LINE_SMOOTH swap antialias?>> [ glEnable ] [ glDisable ] if ]
342 M: scissor-state set-gpu-state*
343 GL_SCISSOR_TEST swap rect>>
344 [ [ loc>> first2 ] [ dim>> first2 ] bi glViewport glEnable ]
347 M: multisample-state set-gpu-state*
349 GL_MULTISAMPLE glEnable
351 [ GL_SAMPLE_ALPHA_TO_COVERAGE swap sample-alpha-to-coverage?>>
352 [ glEnable ] [ glDisable ] if
354 [ GL_SAMPLE_ALPHA_TO_ONE swap sample-alpha-to-one?>>
355 [ glEnable ] [ glDisable ] if
357 [ GL_SAMPLE_COVERAGE swap [ invert-sample-coverage?>> >c-bool ] [ sample-coverage>> ] bi
358 [ swap glSampleCoverage glEnable ] [ drop glDisable ] if*
361 ] [ drop GL_MULTISAMPLE glDisable ] if ;
363 M: stencil-state set-gpu-state*
364 [ ] [ front-mode>> ] [ back-mode>> ] tri or
366 GL_STENCIL_TEST glEnable
367 [ front-mode>> GL_FRONT swap (set-stencil-mode) ]
368 [ back-mode>> GL_BACK swap (set-stencil-mode) ] bi
369 ] [ drop GL_STENCIL_TEST glDisable ] if ;
371 M: depth-range-state set-gpu-state*
372 [ near>> ] [ far>> ] bi glDepthRange ;
374 M: depth-state set-gpu-state*
375 GL_DEPTH_TEST swap comparison>> [ gl-comparison glDepthFunc glEnable ] [ glDisable ] if* ;
377 M: blend-state set-gpu-state*
378 [ ] [ rgb-mode>> ] [ alpha-mode>> ] tri or
381 [ constant-color>> [ first4 glBlendColor ] when* ]
383 [ rgb-mode>> ] [ alpha-mode>> ] bi {
384 [ [ equation>> gl-blend-equation ] bi@ glBlendEquationSeparate ]
387 [ source-function>> gl-blend-function ]
388 [ dest-function>> gl-blend-function ] bi
389 ] bi@ glBlendFuncSeparate
393 ] [ drop GL_BLEND glDisable ] if ;
395 M: mask-state set-gpu-state*
397 [ color>> [ >c-bool ] map first4 glColorMask ]
398 [ depth>> >c-bool glDepthMask ]
399 [ GL_FRONT swap stencil-front>> glStencilMaskSeparate ]
400 [ GL_BACK swap stencil-back>> glStencilMaskSeparate ]
403 : set-gpu-state ( states -- )
405 [ [ set-gpu-state* ] each ]
406 [ set-gpu-state* ] if ; inline
408 : get-gl-bool ( enum -- value )
409 0 c:uchar <ref> [ glGetBooleanv ] keep c:uchar deref c-bool> ;
410 : get-gl-int ( enum -- value )
411 0 c:int <ref> [ glGetIntegerv ] keep c:int deref ;
412 : get-gl-float ( enum -- value )
413 0 c:float <ref> [ glGetFloatv ] keep c:float deref ;
415 : get-gl-bools ( enum count -- value )
416 <byte-array> [ glGetBooleanv ] keep [ c-bool> ] { } map-as ;
417 : get-gl-ints ( enum count -- value )
418 c:int <c-array> [ glGetIntegerv ] keep ;
419 : get-gl-floats ( enum count -- value )
420 c:float <c-array> [ glGetFloatv ] keep ;
422 : get-gl-rect ( enum -- value )
423 4 get-gl-ints first4 [ 2array ] 2bi@ <rect> ;
425 : gl-enabled? ( enum -- ? )
426 glIsEnabled c-bool> ;
428 TYPED: get-viewport-state ( -- viewport-state: viewport-state )
429 GL_VIEWPORT get-gl-rect <viewport-state> ;
431 TYPED: get-scissor-state ( -- scissor-state: scissor-state )
432 GL_SCISSOR_TEST get-gl-bool
433 [ GL_SCISSOR_BOX get-gl-rect ] [ f ] if
436 TYPED: get-multisample-state ( -- multisample-state: multisample-state )
437 GL_MULTISAMPLE gl-enabled?
438 GL_SAMPLE_ALPHA_TO_COVERAGE gl-enabled?
439 GL_SAMPLE_ALPHA_TO_ONE gl-enabled?
440 GL_SAMPLE_COVERAGE gl-enabled? [
441 GL_SAMPLE_COVERAGE_VALUE get-gl-float
442 GL_SAMPLE_COVERAGE_INVERT get-gl-bool
444 <multisample-state> ;
446 TYPED: get-stencil-state ( -- stencil-state: stencil-state )
447 GL_STENCIL_TEST gl-enabled? [
448 GL_STENCIL_REF get-gl-int
449 GL_STENCIL_VALUE_MASK get-gl-int
450 GL_STENCIL_FUNC get-gl-int gl-comparison>
451 GL_STENCIL_FAIL get-gl-int gl-stencil-op>
452 GL_STENCIL_PASS_DEPTH_FAIL get-gl-int gl-stencil-op>
453 GL_STENCIL_PASS_DEPTH_PASS get-gl-int gl-stencil-op>
456 GL_STENCIL_BACK_REF get-gl-int
457 GL_STENCIL_BACK_VALUE_MASK get-gl-int
458 GL_STENCIL_BACK_FUNC get-gl-int gl-comparison>
459 GL_STENCIL_BACK_FAIL get-gl-int gl-stencil-op>
460 GL_STENCIL_BACK_PASS_DEPTH_FAIL get-gl-int gl-stencil-op>
461 GL_STENCIL_BACK_PASS_DEPTH_PASS get-gl-int gl-stencil-op>
466 TYPED: get-depth-range-state ( -- depth-range-state: depth-range-state )
467 GL_DEPTH_RANGE 2 get-gl-floats first2 <depth-range-state> ;
469 TYPED: get-depth-state ( -- depth-state: depth-state )
470 GL_DEPTH_TEST gl-enabled?
471 [ GL_DEPTH_FUNC get-gl-int gl-comparison> ] [ f ] if
474 TYPED: get-blend-state ( -- blend-state: blend-state )
475 GL_BLEND gl-enabled? [
476 GL_BLEND_COLOR 4 get-gl-floats
478 GL_BLEND_EQUATION_RGB get-gl-int gl-blend-equation>
479 GL_BLEND_SRC_RGB get-gl-int gl-blend-function>
480 GL_BLEND_DST_RGB get-gl-int gl-blend-function>
483 GL_BLEND_EQUATION_ALPHA get-gl-int gl-blend-equation>
484 GL_BLEND_SRC_ALPHA get-gl-int gl-blend-function>
485 GL_BLEND_DST_ALPHA get-gl-int gl-blend-function>
490 TYPED: get-mask-state ( -- mask-state: mask-state )
491 GL_COLOR_WRITEMASK 4 get-gl-bools
492 GL_DEPTH_WRITEMASK get-gl-bool
493 GL_STENCIL_WRITEMASK get-gl-int
494 GL_STENCIL_BACK_WRITEMASK get-gl-int
497 TYPED: get-triangle-cull-state ( -- triangle-cull-state: triangle-cull-state )
498 GL_FRONT_FACE get-gl-int gl-triangle-face>
499 GL_CULL_FACE gl-enabled?
500 [ GL_CULL_FACE_MODE get-gl-int gl-triangle-cull> ]
502 <triangle-cull-state> ;
504 TYPED: get-triangle-state ( -- triangle-state: triangle-state )
505 GL_POLYGON_MODE 2 get-gl-ints
506 first2 [ gl-triangle-mode> ] bi@
507 GL_POLYGON_SMOOTH gl-enabled?
510 TYPED: get-point-state ( -- point-state: point-state )
511 GL_VERTEX_PROGRAM_POINT_SIZE gl-enabled?
512 [ f ] [ GL_POINT_SIZE get-gl-float ] if
513 GL_POINT_SPRITE_COORD_ORIGIN get-gl-int gl-point-sprite-origin>
514 GL_POINT_FADE_THRESHOLD_SIZE get-gl-float
517 TYPED: get-line-state ( -- line-state: line-state )
518 GL_LINE_WIDTH get-gl-float
519 GL_LINE_SMOOTH gl-enabled?