diff options
| author | Radosław Kujawa <radoslaw.kujawa@c0ff33.net> | 2026-07-17 14:54:32 +0200 |
|---|---|---|
| committer | Radosław Kujawa <radoslaw.kujawa@c0ff33.net> | 2026-07-17 14:54:32 +0200 |
| commit | 2702c90d7a39fca2a3319c5e915fd290cb31fc70 (patch) | |
| tree | 283c4d851efef7e3a7cd03ba80c87e2bffcdbb2c /src/mesa/drivers/verite/vrdd.c | |
| parent | 836167945ec2c7ad5acdf0aa17ce35ec1b9428a6 (diff) | |
Initial import.
Diffstat (limited to 'src/mesa/drivers/verite/vrdd.c')
| -rw-r--r-- | src/mesa/drivers/verite/vrdd.c | 382 |
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); +} |
