aboutsummaryrefslogtreecommitdiff
path: root/src/mesa/drivers/verite/vrdd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers/verite/vrdd.c')
-rw-r--r--src/mesa/drivers/verite/vrdd.c382
1 files changed, 382 insertions, 0 deletions
diff --git a/src/mesa/drivers/verite/vrdd.c b/src/mesa/drivers/verite/vrdd.c
new file mode 100644
index 0000000..36daf2b
--- /dev/null
+++ b/src/mesa/drivers/verite/vrdd.c
@@ -0,0 +1,382 @@
+/*
+ * 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 device-driver functions
+ */
+
+#include "vrdrv.h"
+
+#include "context.h"
+#include "swrast/swrast.h"
+#include "swrast/s_context.h" /* SWRAST_CONTEXT / _RasterMask */
+#include "swrast_setup/swrast_setup.h"
+#include "array_cache/acache.h"
+#include "tnl/tnl.h"
+
+static const GLubyte *
+vr_get_string(GLcontext *ctx, GLenum pname)
+{
+ (void)ctx;
+ switch (pname) {
+ case GL_VENDOR:
+ return (const GLubyte *)"Rendition";
+ case GL_RENDERER:
+ return (const GLubyte *)"Mesa Rendition Verite V2200";
+ default:
+ return NULL;
+ }
+}
+
+static void
+vr_get_buffer_size(GLframebuffer *buffer, GLuint *width, GLuint *height)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ vrmesa_context *vmesa;
+
+ (void)buffer;
+ if (ctx == NULL)
+ return;
+ vmesa = VRMESA_CONTEXT(ctx);
+ *width = vmesa->rl.v.width;
+ *height = vmesa->rl.v.height;
+}
+
+/* GL_CLEAR..GL_SET (0x1500..0x150F) -> PE ALUMode 4-bit ROP */
+static const GLubyte vr_rop[16] = {
+ 0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE,
+ 0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF,
+};
+
+static void
+vr_update_state(GLcontext *ctx, GLuint new_state)
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+ struct rlgl *rl = &vmesa->rl;
+
+ _swrast_InvalidateState(ctx, new_state);
+ _swsetup_InvalidateState(ctx, new_state);
+ _ac_InvalidateState(ctx, new_state);
+ _tnl_InvalidateState(ctx, new_state);
+
+ /*
+ * PE state used only by the hardware triangle path
+ */
+ if (new_state & _NEW_DEPTH) {
+ /* GL_ALWAYS = compare off; writes are ZBufWrMode's job */
+ rlgl_depth_func(rl,
+ ctx->Depth.Test && ctx->Depth.Func != GL_ALWAYS,
+ ctx->Depth.Func == GL_LESS ? RLGL_Z_LT : RLGL_Z_LE);
+ rlgl_depth_mask(rl, ctx->Depth.Test && ctx->Depth.Mask);
+ }
+ if (new_state & _NEW_COLOR) {
+ GLuint srcf, dstf;
+ GLboolean na;
+
+ rlgl_color_mask(rl, ctx->Color.ColorMask[0],
+ ctx->Color.ColorMask[1], ctx->Color.ColorMask[2]);
+
+ /* honor GL_DITHER (default on): PE 4x4 dither on 565 */
+ rlgl_dither(rl, ctx->Color.DitherFlag);
+
+ if (ctx->Color._LogicOpEnabled) {
+ rlgl_logic_op(rl, 1,
+ vr_rop[ctx->Color.LogicOp - GL_CLEAR]);
+ rlgl_blend(rl, 0, 0, 0);
+ } else {
+ rlgl_logic_op(rl, 0, 0);
+ if (ctx->Color.BlendEnabled &&
+ vrBlendMap(ctx, &srcf, &dstf, &na))
+ rlgl_blend(rl, 1, srcf, dstf);
+ else
+ rlgl_blend(rl, 0, 0, 0);
+ }
+
+ /* TranspReject: reject SrcAlpha <= thresh */
+ if (ctx->Color.AlphaEnabled) {
+ GLint ref = (GLint)(ctx->Color.AlphaRef *
+ 255.0F + 0.5F);
+
+ switch (ctx->Color.AlphaFunc) {
+ case GL_GREATER:
+ rlgl_alpha_test(rl, 1, (uint32_t)ref);
+ break;
+ case GL_GEQUAL:
+ /* pass a >= ref == reject a <= ref-1 */
+ if (ref <= 0)
+ rlgl_alpha_test(rl, 0, 0);
+ else
+ rlgl_alpha_test(rl, 1,
+ (uint32_t)(ref - 1));
+ break;
+ case GL_NEVER:
+ rlgl_alpha_test(rl, 1, 255);
+ break;
+ default: /* ALWAYS or gated shapes */
+ rlgl_alpha_test(rl, 0, 0);
+ break;
+ }
+ } else
+ rlgl_alpha_test(rl, 0, 0);
+ }
+
+ if (new_state & _NEW_FOG) {
+ if (ctx->Fog.Enabled) {
+ GLubyte c[3];
+
+ UNCLAMPED_FLOAT_TO_UBYTE(c[0], ctx->Fog.Color[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(c[1], ctx->Fog.Color[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(c[2], ctx->Fog.Color[2]);
+ rlgl_fog(rl, 1, ((uint32_t)c[0] << 16) |
+ ((uint32_t)c[1] << 8) | (uint32_t)c[2]);
+ } else
+ rlgl_fog(rl, 0, 0);
+ }
+
+ if (new_state & _NEW_SCISSOR) {
+ if (ctx->Scissor.Enabled)
+ rlgl_scissor(rl, ctx->Scissor.X, ctx->Scissor.Y,
+ ctx->Scissor.Width, ctx->Scissor.Height);
+ else
+ rlgl_scissor(rl, 0, 0, rl->v.width, rl->v.height);
+ }
+
+ vrCheckHwRender(ctx);
+}
+
+static void
+vr_clear(GLcontext *ctx, GLbitfield mask, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height)
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+ GLbitfield rest = mask;
+ int cc = 0, cz = 0;
+
+ /* frame boundary for texture evict-pinning (once per GLQuake frame) */
+ vrTexNewFrame();
+
+ if (all && !ctx->Scissor.Enabled) {
+ if ((mask & DD_BACK_LEFT_BIT) != 0 &&
+ ctx->Color.ColorMask[0] && ctx->Color.ColorMask[1] &&
+ ctx->Color.ColorMask[2]) {
+ cc = 1;
+ rest &= ~DD_BACK_LEFT_BIT;
+ }
+ /* engine Z clear writes the max-Z pattern = depth 1.0 */
+ if ((mask & DD_DEPTH_BIT) != 0 && ctx->Depth.Mask &&
+ ctx->Depth.Clear == 1.0) {
+ cz = 1;
+ rest &= ~DD_DEPTH_BIT;
+ }
+ }
+
+ if (cc || cz) {
+ const GLfloat *c = ctx->Color.ClearColor;
+ GLuint r = (GLuint)(c[0] * 255.0F + 0.5F);
+ GLuint g = (GLuint)(c[1] * 255.0F + 0.5F);
+ GLuint b = (GLuint)(c[2] * 255.0F + 0.5F);
+ uint32_t rgb565;
+
+ if (r > 255) r = 255;
+ if (g > 255) g = 255;
+ if (b > 255) b = 255;
+ rgb565 = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3);
+ rlgl_clear(&vmesa->rl, cc, rgb565, cz);
+ vmesa->engine_dirty = GL_TRUE;
+ }
+
+ if (rest != 0)
+ _swrast_Clear(ctx, rest, all, x, y, width, height);
+}
+
+/*
+ * Hardware glDrawPixels.
+ */
+static void
+vr_drawpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels)
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+ static GLushort row565[2048];
+ GLint destX, destY, drawW, drawH, skipPix, skipRows, rowLen, r, i, ch;
+ const GLchan *src;
+
+ if (!ctx->Current.RasterPosValid)
+ return;
+ if ((format != GL_RGBA && format != GL_RGB) || type != CHAN_TYPE ||
+ ctx->_ImageTransferState != 0 || !ctx->Visual.rgbMode ||
+ (SWRAST_CONTEXT(ctx)->_RasterMask & ~CLIP_BIT) != 0 ||
+ ctx->Texture._EnabledCoordUnits != 0 ||
+ unpack->Alignment != 1 || unpack->SwapBytes || unpack->LsbFirst ||
+ ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F)
+ goto slow;
+
+ destX = x; destY = y; drawW = width; drawH = height;
+ skipPix = unpack->SkipPixels; skipRows = unpack->SkipRows;
+ rowLen = unpack->RowLength > 0 ? unpack->RowLength : width;
+
+ /* clip to the draw buffer (mirrors swrast fast_draw_pixels) */
+ if (destX < ctx->DrawBuffer->_Xmin) {
+ skipPix += ctx->DrawBuffer->_Xmin - destX;
+ drawW -= ctx->DrawBuffer->_Xmin - destX;
+ destX = ctx->DrawBuffer->_Xmin;
+ }
+ if (destX + drawW > ctx->DrawBuffer->_Xmax)
+ drawW -= destX + drawW - ctx->DrawBuffer->_Xmax;
+ if (drawW <= 0)
+ return;
+ if (destY < ctx->DrawBuffer->_Ymin) {
+ skipRows += ctx->DrawBuffer->_Ymin - destY;
+ drawH -= ctx->DrawBuffer->_Ymin - destY;
+ destY = ctx->DrawBuffer->_Ymin;
+ }
+ if (destY + drawH > ctx->DrawBuffer->_Ymax)
+ drawH -= destY + drawH - ctx->DrawBuffer->_Ymax;
+ if (drawH <= 0)
+ return;
+
+ /* mem_write needs 32-bit alignment: even x and even width */
+ if ((destX & 1) || (drawW & 1) || drawW > 2048)
+ goto slow;
+
+ ch = (format == GL_RGBA) ? 4 : 3;
+ src = (const GLchan *)pixels + (skipRows * rowLen + skipPix) * ch;
+ for (r = 0; r < drawH; r++) {
+ const GLchan *p = src + (GLint)r * rowLen * ch;
+
+ for (i = 0; i < drawW; i++) {
+ GLchan cr = p[i * ch], cg = p[i * ch + 1],
+ cb = p[i * ch + 2];
+
+ row565[i] = (GLushort)(((cr & 0xf8) << 8) |
+ ((cg & 0xfc) << 3) | (cb >> 3));
+ }
+ (void)rlgl_draw_row(&vmesa->rl, destX, destY + r, drawW, row565);
+ }
+ vmesa->engine_dirty = GL_TRUE;
+ return;
+slow:
+ _swrast_DrawPixels(ctx, x, y, width, height, format, type, unpack,
+ pixels);
+}
+
+/* rl.fb[back] is the draw target, the other buffer is scanned out */
+uint32_t
+vr_fb_base(struct rlgl *rl, GLenum buffer)
+{
+
+ if (buffer == GL_FRONT || buffer == GL_FRONT_LEFT)
+ return rl->fb[rl->back ^ 1];
+ return rl->fb[rl->back]; /* GL_BACK / default */
+}
+
+/*
+ * Hardware glCopyPixels(GL_COLOR).
+ */
+static void
+vr_copypixels(GLcontext *ctx, GLint srcx, GLint srcy, GLsizei width,
+ GLsizei height, GLint destx, GLint desty, GLenum type)
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+ struct rlgl *rl = &vmesa->rl;
+ GLint fbW = (GLint)rl->v.width, fbH = (GLint)rl->v.height;
+ uint32_t sbase, dbase;
+ GLint sy_pe, dy_pe;
+ GLboolean overlap;
+
+ if (type != GL_COLOR || ctx->_ImageTransferState != 0 ||
+ !ctx->Visual.rgbMode ||
+ (SWRAST_CONTEXT(ctx)->_RasterMask & ~CLIP_BIT) != 0 ||
+ ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F)
+ goto slow;
+
+ /* both rects must lie fully inside their buffers (swrast handles
+ * the clipped/border cases correctly) */
+ if (width <= 0 || height <= 0 ||
+ srcx < 0 || srcy < 0 || srcx + width > fbW || srcy + height > fbH ||
+ destx < 0 || desty < 0 || destx + width > fbW ||
+ desty + height > fbH)
+ goto slow;
+
+ sbase = vr_fb_base(rl, ctx->Pixel.ReadBuffer);
+ dbase = vr_fb_base(rl, ctx->Color.DrawBuffer);
+
+ /*
+ * The copy hides the true src/dst relationship from the microcode's
+ * overlap-direction logic
+ */
+ overlap = (sbase == dbase) &&
+ !(destx >= srcx + width || destx + width <= srcx ||
+ desty >= srcy + height || desty + height <= srcy);
+ if (overlap)
+ goto slow;
+
+ /* GL window (bottom-left) -> PE surface (top-left) top edge */
+ sy_pe = fbH - srcy - height;
+ dy_pe = fbH - desty - height;
+ if (rlgl_copy_rect(rl, sbase, fbW, dbase, fbW, srcx, sy_pe,
+ destx, dy_pe, width, height) != 0)
+ goto slow;
+ vmesa->engine_dirty = GL_TRUE;
+ return;
+slow:
+ _swrast_CopyPixels(ctx, srcx, srcy, destx, desty, width, height, type);
+}
+
+static void
+vr_finish(GLcontext *ctx)
+{
+
+ vrFence(VRMESA_CONTEXT(ctx));
+}
+
+static void
+vr_flush(GLcontext *ctx)
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+
+ if (vmesa->engine_dirty)
+ (void)v3d_flush(&vmesa->rl.v);
+}
+
+void
+vrInitDDFuncs(struct dd_function_table *functions)
+{
+
+ functions->GetString = vr_get_string;
+ functions->GetBufferSize = vr_get_buffer_size;
+ functions->UpdateState = vr_update_state;
+ functions->Clear = vr_clear;
+ functions->Finish = vr_finish;
+ functions->Flush = vr_flush;
+ functions->DrawPixels = vr_drawpixels;
+ functions->CopyPixels = vr_copypixels;
+ vrInitTexFuncs(functions);
+}