/*00C14*/ EMIT_STATE(SE_DEPTH_BIAS, rasterizer->SE_DEPTH_BIAS);
/*00C18*/ EMIT_STATE(SE_CONFIG, rasterizer->SE_CONFIG);
}
+ if (unlikely(dirty & (ETNA_DIRTY_SCISSOR | ETNA_DIRTY_FRAMEBUFFER |
+ ETNA_DIRTY_RASTERIZER | ETNA_DIRTY_VIEWPORT))) {
+ struct etna_rasterizer_state *rasterizer = etna_rasterizer_state(ctx->rasterizer);
+
+ uint32_t clip_right =
+ MIN2(ctx->framebuffer.SE_CLIP_RIGHT, ctx->viewport.SE_CLIP_RIGHT);
+ uint32_t clip_bottom =
+ MIN2(ctx->framebuffer.SE_CLIP_BOTTOM, ctx->viewport.SE_CLIP_BOTTOM);
+
+ if (rasterizer->scissor) {
+ clip_right = MIN2(ctx->scissor.SE_CLIP_RIGHT, clip_right);
+ clip_bottom = MIN2(ctx->scissor.SE_CLIP_BOTTOM, clip_bottom);
+ }
+
+ /*00C20*/ EMIT_STATE_FIXP(SE_CLIP_RIGHT, clip_right);
+ /*00C24*/ EMIT_STATE_FIXP(SE_CLIP_BOTTOM, clip_bottom);
+ }
if (unlikely(dirty & (ETNA_DIRTY_SHADER))) {
/*00E00*/ EMIT_STATE(RA_CONTROL, ctx->shader_state.RA_CONTROL);
}
/* PE render targets must be aligned to 64 bytes */
#define ETNA_PE_ALIGNMENT (64)
+/* These demarcate the margin (fixp16) between the computed sizes and the
+ value sent to the chip. These have been set to the numbers used by the
+ Vivante driver on gc2000. They used to be -1 for scissor right and bottom. I
+ am not sure whether older hardware was relying on these or they were just a
+ guess. But if so, these need to be moved to the _specs structure.
+*/
+#define ETNA_SE_SCISSOR_MARGIN_RIGHT (0x1119)
+#define ETNA_SE_SCISSOR_MARGIN_BOTTOM (0x1111)
+#define ETNA_SE_CLIP_MARGIN_RIGHT (0xffff)
+#define ETNA_SE_CLIP_MARGIN_BOTTOM (0xffff)
+
/* GPU chip 3D specs */
struct etna_specs {
/* supports SUPERTILE (64x64) tiling? */
uint32_t SE_SCISSOR_TOP;
uint32_t SE_SCISSOR_RIGHT;
uint32_t SE_SCISSOR_BOTTOM;
+ uint32_t SE_CLIP_RIGHT;
+ uint32_t SE_CLIP_BOTTOM;
};
/* Compiled pipe_viewport_state */
uint32_t SE_SCISSOR_TOP;
uint32_t SE_SCISSOR_RIGHT;
uint32_t SE_SCISSOR_BOTTOM;
+ uint32_t SE_CLIP_RIGHT;
+ uint32_t SE_CLIP_BOTTOM;
uint32_t PE_DEPTH_NEAR;
uint32_t PE_DEPTH_FAR;
};
uint32_t SE_SCISSOR_TOP;
uint32_t SE_SCISSOR_RIGHT;
uint32_t SE_SCISSOR_BOTTOM;
+ uint32_t SE_CLIP_RIGHT;
+ uint32_t SE_CLIP_BOTTOM;
uint32_t RA_MULTISAMPLE_UNK00E04;
uint32_t RA_MULTISAMPLE_UNK00E10[VIVS_RA_MULTISAMPLE_UNK00E10__LEN];
uint32_t RA_CENTROID_TABLE[VIVS_RA_CENTROID_TABLE__LEN];
/* Scissor setup */
cs->SE_SCISSOR_LEFT = 0; /* affected by rasterizer and scissor state as well */
cs->SE_SCISSOR_TOP = 0;
- cs->SE_SCISSOR_RIGHT = (sv->width << 16) - 1;
- cs->SE_SCISSOR_BOTTOM = (sv->height << 16) - 1;
+ cs->SE_SCISSOR_RIGHT = (sv->width << 16) + ETNA_SE_SCISSOR_MARGIN_RIGHT;
+ cs->SE_SCISSOR_BOTTOM = (sv->height << 16) + ETNA_SE_SCISSOR_MARGIN_BOTTOM;
+ cs->SE_CLIP_RIGHT = (sv->width << 16) + ETNA_SE_CLIP_MARGIN_RIGHT;
+ cs->SE_CLIP_BOTTOM = (sv->height << 16) + ETNA_SE_CLIP_MARGIN_BOTTOM;
cs->TS_MEM_CONFIG = ts_mem_config;
{
struct etna_context *ctx = etna_context(pctx);
struct compiled_scissor_state *cs = &ctx->scissor;
+ assert(ss->minx <= ss->maxx);
+ assert(ss->miny <= ss->maxy);
/* note that this state is only used when rasterizer_state->scissor is on */
ctx->scissor_s = *ss;
cs->SE_SCISSOR_LEFT = (ss->minx << 16);
cs->SE_SCISSOR_TOP = (ss->miny << 16);
- cs->SE_SCISSOR_RIGHT = (ss->maxx << 16) - 1;
- cs->SE_SCISSOR_BOTTOM = (ss->maxy << 16) - 1;
+ cs->SE_SCISSOR_RIGHT = (ss->maxx << 16) + ETNA_SE_SCISSOR_MARGIN_RIGHT;
+ cs->SE_SCISSOR_BOTTOM = (ss->maxy << 16) + ETNA_SE_SCISSOR_MARGIN_BOTTOM;
+ cs->SE_CLIP_RIGHT = (ss->maxx << 16) + ETNA_SE_CLIP_MARGIN_RIGHT;
+ cs->SE_CLIP_BOTTOM = (ss->maxy << 16) + ETNA_SE_CLIP_MARGIN_BOTTOM;
ctx->dirty |= ETNA_DIRTY_SCISSOR;
}
/* Compute scissor rectangle (fixp) from viewport.
* Make sure left is always < right and top always < bottom.
*/
- cs->SE_SCISSOR_LEFT = etna_f32_to_fixp16(MAX2(vs->translate[0] - vs->scale[0], 0.0f));
- cs->SE_SCISSOR_TOP = etna_f32_to_fixp16(MAX2(vs->translate[1] - vs->scale[1], 0.0f));
- cs->SE_SCISSOR_RIGHT = etna_f32_to_fixp16(MAX2(vs->translate[0] + vs->scale[0], 0.0f));
- cs->SE_SCISSOR_BOTTOM = etna_f32_to_fixp16(MAX2(vs->translate[1] + vs->scale[1], 0.0f));
-
- if (cs->SE_SCISSOR_LEFT > cs->SE_SCISSOR_RIGHT) {
- uint32_t tmp = cs->SE_SCISSOR_RIGHT;
- cs->SE_SCISSOR_RIGHT = cs->SE_SCISSOR_LEFT;
- cs->SE_SCISSOR_LEFT = tmp;
- }
-
- if (cs->SE_SCISSOR_TOP > cs->SE_SCISSOR_BOTTOM) {
- uint32_t tmp = cs->SE_SCISSOR_BOTTOM;
- cs->SE_SCISSOR_BOTTOM = cs->SE_SCISSOR_TOP;
- cs->SE_SCISSOR_TOP = tmp;
- }
+ cs->SE_SCISSOR_LEFT = etna_f32_to_fixp16(MAX2(vs->translate[0] - fabsf(vs->scale[0]), 0.0f));
+ cs->SE_SCISSOR_TOP = etna_f32_to_fixp16(MAX2(vs->translate[1] - fabsf(vs->scale[1]), 0.0f));
+ uint32_t right_fixp = etna_f32_to_fixp16(MAX2(vs->translate[0] + fabsf(vs->scale[0]), 0.0f));
+ uint32_t bottom_fixp = etna_f32_to_fixp16(MAX2(vs->translate[1] + fabsf(vs->scale[1]), 0.0f));
+ cs->SE_SCISSOR_RIGHT = right_fixp + ETNA_SE_SCISSOR_MARGIN_RIGHT;
+ cs->SE_SCISSOR_BOTTOM = bottom_fixp + ETNA_SE_SCISSOR_MARGIN_BOTTOM;
+ cs->SE_CLIP_RIGHT = right_fixp + ETNA_SE_CLIP_MARGIN_RIGHT;
+ cs->SE_CLIP_BOTTOM = bottom_fixp + ETNA_SE_CLIP_MARGIN_BOTTOM;
cs->PE_DEPTH_NEAR = fui(0.0); /* not affected if depth mode is Z (as in GL) */
cs->PE_DEPTH_FAR = fui(1.0);