/* * Copyright (c) 2026 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Radoslaw Kujawa. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* Canonical rlvec CPU vertex kernels for the verite driver. */ #include #include #include #include "rlvec.h" static void xform_points3_c(float *to, const float m[16], const float *from, int from_stride, int count) { int i; for (i = 0; i < count; i++) { const float *o = (const float *)((const char *)from + (size_t)i * from_stride); float x = o[0], y = o[1], z = o[2]; float *d = to + i * 4; d[0] = m[0] * x + m[4] * y + m[8] * z + m[12]; d[1] = m[1] * x + m[5] * y + m[9] * z + m[13]; d[2] = m[2] * x + m[6] * y + m[10] * z + m[14]; d[3] = m[3] * x + m[7] * y + m[11] * z + m[15]; } } static uint32_t outcode5_c(uint8_t *oc, uint32_t *and_out, const float *clip, int count) { uint32_t or_acc = 0, and_acc = 0x1f; int i; for (i = 0; i < count; i++) { const float *c = clip + i * 4; float x = c[0], y = c[1], z = c[2], w = c[3]; uint32_t o = 0; if (z + w < 0.0f) o |= 0x01; if (w + x < 0.0f) o |= 0x02; if (w - x < 0.0f) o |= 0x04; if (w + y < 0.0f) o |= 0x08; if (w - y < 0.0f) o |= 0x10; oc[i] = (uint8_t)o; or_acc |= o; and_acc &= o; } *and_out = and_acc; return or_acc; } static void project_c(float *out9, const float *clip, const float *attr, const float k[8], int count) { int i; for (i = 0; i < count; i++) { const float *c = clip + i * 4; const float *a = attr + i * 6; float *s = out9 + i * 9; float q = 1.0f / c[3]; float zz; s[0] = a[0]; s[1] = a[1]; s[2] = a[2]; s[3] = k[0] + k[1] * (c[0] * q); s[4] = k[2] - k[3] * (c[1] * q); zz = k[4] + k[5] * (c[2] * q); if (zz < 0.0f) zz = 0.0f; if (zz > 65000.0f) zz = 65000.0f; s[5] = zz; s[6] = a[4] * k[6]; s[7] = a[5] * k[7]; s[8] = q; } } static uint32_t * emit_tris_c(uint32_t *dst, const float *verts9, const uint8_t *idx, int ntris, uint32_t hdr) { int t, k; for (t = 0; t < ntris; t++) { *dst++ = hdr; for (k = 0; k < 3; k++) { memcpy(dst, verts9 + (uint32_t)idx[t * 3 + k] * 9, 9 * sizeof(float)); dst += 9; } } return dst; } const struct rlvec_ops rlvec_c = { xform_points3_c, outcode5_c, project_c, emit_tris_c, }; #ifdef RLVEC_PPC rlvec_xform_points3_fn rlvec_xform_points3_ppc; rlvec_outcode5_fn rlvec_outcode5_ppc; rlvec_emit_tris_fn rlvec_emit_tris_ppc; const struct rlvec_ops rlvec_ppc = { rlvec_xform_points3_ppc, outcode5_c, project_c, rlvec_emit_tris_ppc, }; #endif struct rlvec_ops rlvec; void rlvec_init(void) { static int done; const char *noasm; if (done) return; done = 1; rlvec = rlvec_c; #ifdef RLVEC_PPC rlvec = rlvec_ppc; noasm = getenv("RLGL_NOASM"); if (noasm != NULL) { if (strcmp(noasm, "1") == 0) { rlvec = rlvec_c; fprintf(stderr, "rlvec: all-C forced\n"); } else { if (strstr(noasm, "xform") != NULL) rlvec.xform_points3 = rlvec_c.xform_points3; if (strstr(noasm, "outcode") != NULL) rlvec.outcode5 = rlvec_c.outcode5; if (strstr(noasm, "project") != NULL) rlvec.project = rlvec_c.project; if (strstr(noasm, "emit") != NULL) rlvec.emit_tris = rlvec_c.emit_tris; fprintf(stderr, "rlvec: C forced for: %s\n", noasm); } } #else (void)noasm; #endif }