diff --git a/iris-hostgl/src/ext.rs b/iris-hostgl/src/ext.rs index 54f09f084..d48e7bffb 100644 --- a/iris-hostgl/src/ext.rs +++ b/iris-hostgl/src/ext.rs @@ -4,7 +4,12 @@ // calls are the same as a core or ARB call it has, and the ones emulated in // emul.rs. (Checked against SGI's own libGL list and the Mac's; carried over // as generated, not regenerated here.) -pub const EXTENSIONS: &str = "GL_ARB_multitexture GL_EXT_abgr GL_EXT_blend_color GL_EXT_blend_logic_op GL_EXT_blend_minmax GL_EXT_blend_subtract GL_EXT_convolution GL_EXT_copy_texture GL_EXT_histogram GL_EXT_packed_pixels GL_EXT_polygon_offset GL_EXT_subtexture GL_EXT_texture GL_EXT_texture3D GL_EXT_texture_object GL_EXT_vertex_array GL_SGIS_detail_texture GL_SGIS_fog_function GL_SGIS_generate_mipmap GL_SGIS_multisample GL_SGIS_multitexture GL_SGIS_point_parameters GL_SGIS_sharpen_texture GL_SGIS_texture4D GL_SGIS_texture_edge_clamp GL_SGIS_texture_filter4 GL_SGIS_texture_lod GL_SGIS_texture_select GL_SGIX_clipmap GL_SGIX_flush_raster GL_SGIX_fog_offset GL_SGIX_interlace GL_SGIX_pixel_texture GL_SGIX_reference_plane GL_SGIX_shadow GL_SGIX_sprite GL_SGIX_texture_add_env GL_SGIX_texture_scale_bias GL_SGI_color_matrix GL_SGI_color_table GL_SGI_texture_color_table"; +// Of IMPACT's own list (IMPACT/2/2/4, 6.5.22), all are here but +// GL_SGIX_list_priority (glListParameter*, which this library does not +// have): GL_SGIS_texture_border_clamp's GL_CLAMP_TO_BORDER_SGIS is core +// GL_CLAMP_TO_BORDER, and GL_SGIX_texture_multi_buffer is a hint the guest +// library takes (its glHint keeps GL_TEXTURE_MULTI_BUFFER_HINT_SGIX itself). +pub const EXTENSIONS: &str = "GL_ARB_multitexture GL_EXT_abgr GL_EXT_blend_color GL_EXT_blend_logic_op GL_EXT_blend_minmax GL_EXT_blend_subtract GL_EXT_convolution GL_EXT_copy_texture GL_EXT_histogram GL_EXT_packed_pixels GL_EXT_polygon_offset GL_EXT_subtexture GL_EXT_texture GL_EXT_texture3D GL_EXT_texture_object GL_EXT_vertex_array GL_SGIS_detail_texture GL_SGIS_fog_function GL_SGIS_generate_mipmap GL_SGIS_multisample GL_SGIS_multitexture GL_SGIS_point_parameters GL_SGIS_sharpen_texture GL_SGIS_texture4D GL_SGIS_texture_border_clamp GL_SGIS_texture_edge_clamp GL_SGIS_texture_filter4 GL_SGIS_texture_lod GL_SGIS_texture_select GL_SGIX_clipmap GL_SGIX_flush_raster GL_SGIX_fog_offset GL_SGIX_interlace GL_SGIX_pixel_texture GL_SGIX_reference_plane GL_SGIX_shadow GL_SGIX_sprite GL_SGIX_texture_add_env GL_SGIX_texture_multi_buffer GL_SGIX_texture_scale_bias GL_SGI_color_matrix GL_SGI_color_table GL_SGI_texture_color_table"; /* * What a guest program is told it is talking to. diff --git a/iris-hostgl/tools/glshim.py b/iris-hostgl/tools/glshim.py index 291800a53..c5bf10f72 100644 --- a/iris-hostgl/tools/glshim.py +++ b/iris-hostgl/tools/glshim.py @@ -103,8 +103,81 @@ "glEnable": "if (hgl_index_mode && cap == GL_LOGIC_OP) cap = GL_COLOR_LOGIC_OP;", "glDisable": "if (hgl_index_mode && cap == GL_LOGIC_OP) cap = GL_COLOR_LOGIC_OP;", "glIsEnabled": "if (hgl_index_mode && cap == GL_LOGIC_OP) cap = GL_COLOR_LOGIC_OP;", + # GL_TEXTURE_MULTI_BUFFER_HINT_SGIX (GL_SGIX_texture_multi_buffer): a + # hint about IMPACT's texture memory, which the host has no use for and + # would refuse; taken here. + "glHint": "if (target == 0x812E) return;", + # Drawing indices: the host's RGBA GL turns them into colours through its + # pixel maps (all 0), so they are encoded here as an index context draws. + "glDrawPixels": "if (hgl_index_mode && format == GL_COLOR_INDEX) { hgl_draw_index(width, height, type, pixels); return; }", + # Reading indices back: the host has only the RGBA they were drawn as. + "glReadPixels": "if (hgl_index_mode && format == GL_COLOR_INDEX) { hgl_read_index(x, y, width, height, type, pixels); return; }", } +# lmcolor(LMC_COLOR) for SGI's IRIS GL (hgl_lmc in the guest's glshim_rt.c): +# the program's GL_LIGHTING, and a glBegin held until its first vertex while +# the mode is on. Which of a colour and a normal came last, IGLOO says itself. +GUEST_HOOKS.update({ + **{f"glVertex{n}{t}{v}": "if (hgl_lmc_pending) hgl_lmc_vertex();" + for n in ("2", "3", "4") for t in ("d", "f", "i", "s") for v in ("", "v")}, + "glBegin": "if (hgl_lmc && hgl_lmc_begin(mode)) return;", + "glEnd": "if (hgl_lmc_pending && hgl_lmc_end()) return;", + "glEnable": "hgl_lmc_lighting(cap, 1);", + "glDisable": "hgl_lmc_lighting(cap, 0);", +}) + +# swaptmesh for SGI's IRIS GL (hgl_tm in the guest's glshim_rt.c): inside one +# of its triangle meshes, each vertex and the normal, colour and texture +# coordinate it was sent with are kept, so that a swap can send the older of +# the last two again. Values as floats: an integer colour or normal is +# normalized as OpenGL does it. +_TM_NORM = {"b": "127.0", "s": "32767.0", "i": "2147483647.0"} +_TM_UNORM = {"ub": "255.0", "us": "65535.0", "ui": "4294967295.0"} + + +def _tm_args(names, n, t, v, norm): + """C expressions for n values of type t, scalar names or v[i], as doubles.""" + vals = [f"v[{i}]" if v else names[i] for i in range(n)] + if norm and t in _TM_NORM: + # OpenGL 1.1: (2c + 1) / (2^b - 1) + return [f"(2.0 * {x} + 1.0) / (2.0 * {_TM_NORM[t]} + 1.0)" for x in vals] + if norm and t in _TM_UNORM: + return [f"{x} / {_TM_UNORM[t]}" for x in vals] + return [f"(double){x}" for x in vals] + + +def _tm_hook(kind, names, n, t, v, norm, fill): + a = _tm_args(names, n, t, v, norm) + fill[n:] + return f"if (hgl_tm && !hgl_tm_internal) hgl_tm_attr({kind}, {', '.join(a)});" + + +def _add_hook(name, code, first=False): + old = GUEST_HOOKS.get(name) + GUEST_HOOKS[name] = code if old is None else (f"{code} {old}" if first else f"{old} {code}") + + +for n in ("3", "4"): + for t in ("b", "d", "f", "i", "s", "ub", "ui", "us"): + for v in ("", "v"): + _add_hook(f"glColor{n}{t}{v}", _tm_hook("HGL_TM_COLOUR", ["red", "green", "blue", "alpha"], int(n), t, v, True, + ["0", "0", "0", "1.0"])) +for t in ("b", "d", "f", "i", "s"): + for v in ("", "v"): + _add_hook(f"glNormal3{t}{v}", _tm_hook("HGL_TM_NORMAL", ["nx", "ny", "nz"], 3, t, v, True, ["0", "0", "0", "0"])) +for n in ("1", "2", "3", "4"): + for t in ("d", "f", "i", "s"): + for v in ("", "v"): + _add_hook(f"glTexCoord{n}{t}{v}", _tm_hook("HGL_TM_TEXCOORD", ["s", "t", "r", "q"], int(n), t, v, False, + ["0", "0", "0", "1.0"])) +for n in ("2", "3", "4"): + for t in ("d", "f", "i", "s"): + for v in ("", "v"): + # After lmcolor's: the vertex is sent after its held glBegin. + _add_hook(f"glVertex{n}{t}{v}", _tm_hook("HGL_TM_VERTEX", ["x", "y", "z", "w"], int(n), t, v, False, + ["0", "0", "0", "1.0"])) +# Before lmcolor's, which may return: a new strip starts with no vertices kept. +_add_hook("glBegin", "if (hgl_tm) hgl_tm_begin();", first=True) + # ... and these after a state query has its answer: an index context answers # for its index state, which the host does not have. GUEST_AFTER = { @@ -112,6 +185,8 @@ "glGetIntegerv": "if (hgl_index_mode) hgl_index_geti(pname, data);", "glGetFloatv": "if (hgl_index_mode) hgl_index_getf(pname, data);", "glGetDoublev": "if (hgl_index_mode) hgl_index_getd(pname, data);", + # The program's lighting back on after a primitive drawn unlit (hgl_lmc). + "glEnd": "if (hgl_lmc_off) hgl_lmc_after_end();", } # The encoders also report what memory the host will read: hgl_ref for a