📄 r300_state.c
字号:
{ (void)face; (void)mode; r300UpdatePolygonMode(ctx);}/* ============================================================= * Stencil */static int translate_stencil_op(int op){ switch (op) { case GL_KEEP: return R300_ZS_KEEP; case GL_ZERO: return R300_ZS_ZERO; case GL_REPLACE: return R300_ZS_REPLACE; case GL_INCR: return R300_ZS_INCR; case GL_DECR: return R300_ZS_DECR; case GL_INCR_WRAP_EXT: return R300_ZS_INCR_WRAP; case GL_DECR_WRAP_EXT: return R300_ZS_DECR_WRAP; case GL_INVERT: return R300_ZS_INVERT; default: WARN_ONCE("Do not know how to translate stencil op"); return R300_ZS_KEEP; } return 0;}static void r300ShadeModel(GLcontext * ctx, GLenum mode){ r300ContextPtr rmesa = R300_CONTEXT(ctx); R300_STATECHANGE(rmesa, shade); rmesa->hw.shade.cmd[1] = 0x00000002; switch (mode) { case GL_FLAT: rmesa->hw.shade.cmd[2] = R300_RE_SHADE_MODEL_FLAT; break; case GL_SMOOTH: rmesa->hw.shade.cmd[2] = R300_RE_SHADE_MODEL_SMOOTH; break; default: return; } rmesa->hw.shade.cmd[3] = 0x00000000; rmesa->hw.shade.cmd[4] = 0x00000000;}static void r300StencilFuncSeparate(GLcontext * ctx, GLenum face, GLenum func, GLint ref, GLuint mask){ r300ContextPtr rmesa = R300_CONTEXT(ctx); GLuint refmask = (((ctx->Stencil. Ref[0] & 0xff) << R300_STENCILREF_SHIFT) | ((ctx-> Stencil. ValueMask [0] & 0xff) << R300_STENCILMASK_SHIFT)); GLuint flag; R300_STATECHANGE(rmesa, zs); rmesa->hw.zs.cmd[R300_ZS_CNTL_0] |= R300_STENCIL_FRONT_BACK; rmesa->hw.zs.cmd[R300_ZS_CNTL_1] &= ~((R300_ZS_MASK << R300_S_FRONT_FUNC_SHIFT) | (R300_ZS_MASK << R300_S_BACK_FUNC_SHIFT)); rmesa->hw.zs.cmd[R300_ZS_CNTL_2] &= ~((R300_STENCILREF_MASK << R300_STENCILREF_SHIFT) | (R300_STENCILREF_MASK << R300_STENCILMASK_SHIFT)); flag = translate_func(ctx->Stencil.Function[0]); rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |= (flag << R300_S_FRONT_FUNC_SHIFT); if (ctx->Stencil._TestTwoSide) flag = translate_func(ctx->Stencil.Function[1]); rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |= (flag << R300_S_BACK_FUNC_SHIFT); rmesa->hw.zs.cmd[R300_ZS_CNTL_2] |= refmask;}static void r300StencilMaskSeparate(GLcontext * ctx, GLenum face, GLuint mask){ r300ContextPtr rmesa = R300_CONTEXT(ctx); R300_STATECHANGE(rmesa, zs); rmesa->hw.zs.cmd[R300_ZS_CNTL_2] &= ~(R300_STENCILREF_MASK << R300_STENCILWRITEMASK_SHIFT); rmesa->hw.zs.cmd[R300_ZS_CNTL_2] |= (ctx->Stencil. WriteMask[0] & R300_STENCILREF_MASK) << R300_STENCILWRITEMASK_SHIFT;}static void r300StencilOpSeparate(GLcontext * ctx, GLenum face, GLenum fail, GLenum zfail, GLenum zpass){ r300ContextPtr rmesa = R300_CONTEXT(ctx); R300_STATECHANGE(rmesa, zs); /* It is easier to mask what's left.. */ rmesa->hw.zs.cmd[R300_ZS_CNTL_1] &= (R300_ZS_MASK << R300_Z_FUNC_SHIFT) | (R300_ZS_MASK << R300_S_FRONT_FUNC_SHIFT) | (R300_ZS_MASK << R300_S_BACK_FUNC_SHIFT); rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |= (translate_stencil_op(ctx->Stencil.FailFunc[0]) << R300_S_FRONT_SFAIL_OP_SHIFT) | (translate_stencil_op(ctx->Stencil.ZFailFunc[0]) << R300_S_FRONT_ZFAIL_OP_SHIFT) | (translate_stencil_op(ctx->Stencil.ZPassFunc[0]) << R300_S_FRONT_ZPASS_OP_SHIFT); if (ctx->Stencil._TestTwoSide) { rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |= (translate_stencil_op(ctx->Stencil.FailFunc[1]) << R300_S_BACK_SFAIL_OP_SHIFT) | (translate_stencil_op(ctx->Stencil.ZFailFunc[1]) << R300_S_BACK_ZFAIL_OP_SHIFT) | (translate_stencil_op(ctx->Stencil.ZPassFunc[1]) << R300_S_BACK_ZPASS_OP_SHIFT); } else { rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |= (translate_stencil_op(ctx->Stencil.FailFunc[0]) << R300_S_BACK_SFAIL_OP_SHIFT) | (translate_stencil_op(ctx->Stencil.ZFailFunc[0]) << R300_S_BACK_ZFAIL_OP_SHIFT) | (translate_stencil_op(ctx->Stencil.ZPassFunc[0]) << R300_S_BACK_ZPASS_OP_SHIFT); }}/* ============================================================= * Window position and viewport transformation *//* * To correctly position primitives: */#define SUBPIXEL_X 0.125#define SUBPIXEL_Y 0.125static void r300UpdateWindow(GLcontext * ctx){ r300ContextPtr rmesa = R300_CONTEXT(ctx); __DRIdrawablePrivate *dPriv = rmesa->radeon.dri.drawable; GLfloat xoffset = dPriv ? (GLfloat) dPriv->x : 0; GLfloat yoffset = dPriv ? (GLfloat) dPriv->y + dPriv->h : 0; const GLfloat *v = ctx->Viewport._WindowMap.m; GLfloat sx = v[MAT_SX]; GLfloat tx = v[MAT_TX] + xoffset + SUBPIXEL_X; GLfloat sy = -v[MAT_SY]; GLfloat ty = (-v[MAT_TY]) + yoffset + SUBPIXEL_Y; GLfloat sz = v[MAT_SZ] * rmesa->state.depth.scale; GLfloat tz = v[MAT_TZ] * rmesa->state.depth.scale; R300_FIREVERTICES(rmesa); R300_STATECHANGE(rmesa, vpt); rmesa->hw.vpt.cmd[R300_VPT_XSCALE] = r300PackFloat32(sx); rmesa->hw.vpt.cmd[R300_VPT_XOFFSET] = r300PackFloat32(tx); rmesa->hw.vpt.cmd[R300_VPT_YSCALE] = r300PackFloat32(sy); rmesa->hw.vpt.cmd[R300_VPT_YOFFSET] = r300PackFloat32(ty); rmesa->hw.vpt.cmd[R300_VPT_ZSCALE] = r300PackFloat32(sz); rmesa->hw.vpt.cmd[R300_VPT_ZOFFSET] = r300PackFloat32(tz);}static void r300Viewport(GLcontext * ctx, GLint x, GLint y, GLsizei width, GLsizei height){ /* Don't pipeline viewport changes, conflict with window offset * setting below. Could apply deltas to rescue pipelined viewport * values, or keep the originals hanging around. */ r300UpdateWindow(ctx);}static void r300DepthRange(GLcontext * ctx, GLclampd nearval, GLclampd farval){ r300UpdateWindow(ctx);}void r300UpdateViewportOffset(GLcontext * ctx){ r300ContextPtr rmesa = R300_CONTEXT(ctx); __DRIdrawablePrivate *dPriv = ((radeonContextPtr) rmesa)->dri.drawable; GLfloat xoffset = (GLfloat) dPriv->x; GLfloat yoffset = (GLfloat) dPriv->y + dPriv->h; const GLfloat *v = ctx->Viewport._WindowMap.m; GLfloat tx = v[MAT_TX] + xoffset + SUBPIXEL_X; GLfloat ty = (-v[MAT_TY]) + yoffset + SUBPIXEL_Y; if (rmesa->hw.vpt.cmd[R300_VPT_XOFFSET] != r300PackFloat32(tx) || rmesa->hw.vpt.cmd[R300_VPT_YOFFSET] != r300PackFloat32(ty)) { /* Note: this should also modify whatever data the context reset * code uses... */ R300_STATECHANGE(rmesa, vpt); rmesa->hw.vpt.cmd[R300_VPT_XOFFSET] = r300PackFloat32(tx); rmesa->hw.vpt.cmd[R300_VPT_YOFFSET] = r300PackFloat32(ty); } radeonUpdateScissor(ctx);}/** * Tell the card where to render (offset, pitch). * Effected by glDrawBuffer, etc */void r300UpdateDrawBuffer(GLcontext * ctx){ r300ContextPtr rmesa = R300_CONTEXT(ctx); r300ContextPtr r300 = rmesa; struct gl_framebuffer *fb = ctx->DrawBuffer; driRenderbuffer *drb; if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) { /* draw to front */ drb = (driRenderbuffer *) fb->Attachment[BUFFER_FRONT_LEFT]. Renderbuffer; } else if (fb->_ColorDrawBufferIndexes[0] == BUFFER_BACK_LEFT) { /* draw to back */ drb = (driRenderbuffer *) fb->Attachment[BUFFER_BACK_LEFT]. Renderbuffer; } else { /* drawing to multiple buffers, or none */ return; } assert(drb); assert(drb->flippedPitch); R300_STATECHANGE(rmesa, cb); r300->hw.cb.cmd[R300_CB_OFFSET] = drb->flippedOffset + //r300->radeon.state.color.drawOffset + r300->radeon.radeonScreen->fbLocation; r300->hw.cb.cmd[R300_CB_PITCH] = drb->flippedPitch; //r300->radeon.state.color.drawPitch; if (r300->radeon.radeonScreen->cpp == 4) r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_FORMAT_ARGB8888; else r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_FORMAT_RGB565; if (r300->radeon.sarea->tiling_enabled) r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_TILE_ENABLE;#if 0 R200_STATECHANGE(rmesa, ctx); /* Note: we used the (possibly) page-flipped values */ rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = ((drb->flippedOffset + rmesa->r200Screen->fbLocation) & R200_COLOROFFSET_MASK); rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = drb->flippedPitch; if (rmesa->sarea->tiling_enabled) { rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= R200_COLOR_TILE_ENABLE; }#endif}static voidr300FetchStateParameter(GLcontext * ctx, const gl_state_index state[STATE_LENGTH], GLfloat * value){ r300ContextPtr r300 = R300_CONTEXT(ctx); switch (state[0]) { case STATE_INTERNAL: switch (state[1]) { case STATE_R300_WINDOW_DIMENSION: value[0] = r300->radeon.dri.drawable->w * 0.5f; /* width*0.5 */ value[1] = r300->radeon.dri.drawable->h * 0.5f; /* height*0.5 */ value[2] = 0.5F; /* for moving range [-1 1] -> [0 1] */ value[3] = 1.0F; /* not used */ break; case STATE_R300_TEXRECT_FACTOR:{ struct gl_texture_object *t = ctx->Texture.Unit[state[2]].CurrentRect; if (t && t->Image[0][t->BaseLevel]) { struct gl_texture_image *image = t->Image[0][t->BaseLevel]; value[0] = 1.0 / image->Width2; value[1] = 1.0 / image->Height2; } else { value[0] = 1.0; value[1] = 1.0; } value[2] = 1.0; value[3] = 1.0; break; } default: break; } break; default: break; }}/** * Update R300's own internal state parameters. * For now just STATE_R300_WINDOW_DIMENSION */void r300UpdateStateParameters(GLcontext * ctx, GLuint new_state){ struct r300_fragment_program *fp; struct gl_program_parameter_list *paramList; GLuint i; if (!(new_state & (_NEW_BUFFERS | _NEW_PROGRAM))) return; fp = (struct r300_fragment_program *)ctx->FragmentProgram._Current; if (!fp) return; paramList = fp->mesa_program.Base.Parameters; if (!paramList) return; for (i = 0; i < paramList->NumParameters; i++) { if (paramList->Parameters[i].Type == PROGRAM_STATE_VAR) { r300FetchStateParameter(ctx, paramList->Parameters[i]. StateIndexes, paramList->ParameterValues[i]); } }}/* ============================================================= * Polygon state */static void r300PolygonOffset(GLcontext * ctx, GLfloat factor, GLfloat units){ r300ContextPtr rmesa = R300_CONTEXT(ctx); GLfloat constant = units; switch (ctx->Visual.depthBits) { case 16: constant *= 4.0; break; case 24: constant *= 2.0; break; } factor *= 12.0;/* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */ R300_STATECHANGE(rmesa, zbs); rmesa->hw.zbs.cmd[R300_ZBS_T_FACTOR] = r300PackFloat32(factor); rmesa->hw.zbs.cmd[R300_ZBS_T_CONSTANT] = r300PackFloat32(constant); rmesa->hw.zbs.cmd[R300_ZBS_W_FACTOR] = r300PackFloat32(factor); rmesa->hw.zbs.cmd[R300_ZBS_W_CONSTANT] = r300PackFloat32(constant);}/* Routing and texture-related *//* r300 doesnt handle GL_CLAMP and GL_MIRROR_CLAMP_EXT correctly when filter is NEAREST. * Since texwrap produces same results for GL_CLAMP and GL_CLAMP_TO_EDGE we use them instead. * We need to recalculate wrap modes whenever filter mode is changed because someone might do: * glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); * glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); * glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); * Since r300 completely ignores R300_TX_CLAMP when either min or mag is nearest it cant handle * combinations where only one of them is nearest. */static unsigned long gen_fixed_filter(unsigned long f){ unsigned long mag, min, needs_fixing = 0; //return f; /* We ignore MIRROR bit so we dont have to do everything twice */ if ((f & ((7 - 1) << R300_TX_WRAP_S_SHIFT)) == (R300_TX_CLAMP << R300_TX_WRAP_S_SHIFT)) { needs_fixing |= 1; } if ((f & ((7 - 1) << R300_TX_WRAP_T_SHIFT)) == (R300_TX_CLAMP << R300_TX_WRAP_T_SHIFT)) { needs_fixing |= 2; } if ((f & ((7 - 1) << R300_TX_WRAP_R_SHIFT)) == (R300_TX_CLAMP << R300_TX_WRAP_R_SHIFT)) { needs_fixing |= 4; } if (!needs_fixing) return f; mag = f & R300_TX_MAG_FILTER_MASK; min = f & (R300_TX_MIN_FILTER_MASK|R300_TX_MIN_FILTER_MIP_MASK); /* TODO: Check for anisto filters too */ if ((mag != R300_TX_MAG_FILTER_NEAREST) && (min != R300_TX_MIN_FILTER_NEAREST)) return f; /* r300 cant handle these modes hence we force nearest to linear */ if ((mag == R300_TX_MAG_FILTER_NEAREST) && (min != R300_TX_MIN_FILTER_NEAREST)) { f &= ~R300_TX_MAG_FILTER_NEAREST; f |= R300_TX_MAG_FILTER_LINEAR; return f; } if ((min == R300_TX_MIN_FILTER_NEAREST) && (mag != R300_TX_MAG_FILTER_NEAREST)) { f &= ~R300_TX_MIN_FILTER_NEAREST; f |= R300_TX_MIN_FILTER_LINEAR; return f; } /* Both are nearest */ if (needs_fixing & 1) { f &= ~((7 - 1) << R300_TX_WRAP_S_SHIFT); f |= R300_TX_CLAMP_TO_EDGE << R300_TX_WRAP_S_SHIFT; } if (needs_fixing & 2) { f &= ~((7 - 1) << R300_TX_WRAP_T_SHIFT); f |= R300_TX_CLAMP_TO_EDGE << R300_TX_WRAP_T_SHIFT; } if (needs_fixing & 4) { f &= ~((7 - 1) << R300_TX_WRAP_R_SHIFT); f |= R300_TX_CLAMP_TO_EDGE << R300_TX_WRAP_R_SHIFT; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -