/* * 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. */ /* * veritemesa swrast spans over the /dev/verite3d VRAM mmap window. */ #include "vrdrv.h" #include "imports.h" #include "swrast/swrast.h" void vrFence(vrmesa_context *vmesa) { if (vmesa->engine_dirty) { rlgl_finish(&vmesa->rl); vmesa->engine_dirty = GL_FALSE; VRP_COUNT(fences); } } /* * Base of the buffer swrast is currently addressing. */ static GLubyte * vr_span_base(vrmesa_context *vmesa) { struct rlgl *rl = &vmesa->rl; uint32_t fb; vrFence(vmesa); fb = vmesa->span_front ? rl->fb[rl->back ^ 1] : rl->fb[rl->back]; return (GLubyte *)(uintptr_t)v3d_vram(&rl->v) + fb; } static GLushort * vr_zrow(vrmesa_context *vmesa, GLint y) { struct rlgl *rl = &vmesa->rl; vrFence(vmesa); return (GLushort *)((GLubyte *)(uintptr_t)v3d_vram(&rl->v) + rl->zbuf + (size_t)(rl->v.height - 1 - y) * rl->v.stride); } static void vr_set_buffer(GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit) { vrmesa_context *vmesa = VRMESA_CONTEXT(ctx); (void)buffer; switch (bufferBit) { case DD_FRONT_LEFT_BIT: vmesa->span_front = GL_TRUE; break; case DD_BACK_LEFT_BIT: vmesa->span_front = GL_FALSE; break; default: _mesa_problem(ctx, "bad bufferBit in vr_set_buffer"); } } #define VR_SWAP16(x) ((GLushort)((((x) & 0xff) << 8) | ((x) >> 8))) #define NAME(PREFIX) PREFIX##_565 #define SPAN_VARS \ vrmesa_context *vmesa = VRMESA_CONTEXT((GLcontext *)ctx); \ GLubyte *vrbuf = vr_span_base(vmesa); \ const GLuint vrstride = vmesa->rl.v.stride; \ const GLint vrheight = vmesa->rl.v.height; #define INIT_PIXEL_PTR(P, X, Y) \ GLushort *P = (GLushort *)(vrbuf + \ (size_t)(vrheight - 1 - (Y)) * vrstride + (X) * 2) #define INC_PIXEL_PTR(P) P += 1 #define STORE_RGB_PIXEL(P, X, Y, R, G, B) \ *P = VR_SWAP16((((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | \ ((B) >> 3)) #define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \ *P = VR_SWAP16((((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | \ ((B) >> 3)) #define FETCH_RGBA_PIXEL(R, G, B, A, P) \ do { \ GLushort px_ = VR_SWAP16(*P); \ R = (((px_ >> 8) & 0xf8) | ((px_ >> 11) & 0x7)); \ G = (((px_ >> 3) & 0xfc) | ((px_ >> 5) & 0x3)); \ B = (((px_ << 3) & 0xf8) | ((px_ ) & 0x7)); \ A = CHAN_MAX; \ } while (0) #include "swrast/s_spantemp.h" static void vr_write_depth_span(GLcontext *ctx, GLuint n, GLint x, GLint y, const GLdepth depth[], const GLubyte mask[]) { GLushort *zrow = vr_zrow(VRMESA_CONTEXT(ctx), y) + x; GLuint i; for (i = 0; i < n; i++) if (mask == NULL || mask[i]) zrow[i] = VR_SWAP16((GLushort)depth[i]); } static void vr_write_mono_depth_span(GLcontext *ctx, GLuint n, GLint x, GLint y, const GLdepth depth, const GLubyte mask[]) { GLushort *zrow = vr_zrow(VRMESA_CONTEXT(ctx), y) + x; GLuint i; for (i = 0; i < n; i++) if (mask == NULL || mask[i]) zrow[i] = VR_SWAP16((GLushort)depth); } static void vr_read_depth_span(GLcontext *ctx, GLuint n, GLint x, GLint y, GLdepth depth[]) { const GLushort *zrow = vr_zrow(VRMESA_CONTEXT(ctx), y) + x; GLuint i; for (i = 0; i < n; i++) depth[i] = VR_SWAP16(zrow[i]); } static void vr_write_depth_pixels(GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], const GLdepth depth[], const GLubyte mask[]) { vrmesa_context *vmesa = VRMESA_CONTEXT(ctx); GLuint i; for (i = 0; i < n; i++) if (mask == NULL || mask[i]) vr_zrow(vmesa, y[i])[x[i]] = VR_SWAP16((GLushort)depth[i]); } static void vr_read_depth_pixels(GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], GLdepth depth[]) { vrmesa_context *vmesa = VRMESA_CONTEXT(ctx); GLuint i; for (i = 0; i < n; i++) depth[i] = VR_SWAP16(vr_zrow(vmesa, y[i])[x[i]]); } void vrInitSpanFuncs(GLcontext *ctx) { struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx); swdd->SetBuffer = vr_set_buffer; swdd->WriteRGBASpan = write_rgba_span_565; swdd->WriteRGBSpan = write_rgb_span_565; swdd->WriteMonoRGBASpan = write_monorgba_span_565; swdd->WriteRGBAPixels = write_rgba_pixels_565; swdd->WriteMonoRGBAPixels = write_monorgba_pixels_565; swdd->ReadRGBASpan = read_rgba_span_565; swdd->ReadRGBAPixels = read_rgba_pixels_565; swdd->WriteDepthSpan = vr_write_depth_span; swdd->WriteMonoDepthSpan = vr_write_mono_depth_span; swdd->ReadDepthSpan = vr_read_depth_span; swdd->WriteDepthPixels = vr_write_depth_pixels; swdd->ReadDepthPixels = vr_read_depth_pixels; }