return PIPE_ENDIAN_LITTLE;
case PIPE_CAP_TGSI_VS_LAYER:
return 0;
+ case PIPE_CAP_MAX_VIEWPORTS:
+ return NV50_MAX_VIEWPORTS;
default:
NOUVEAU_ERR("unknown PIPE_CAP %d\n", param);
return 0;
BEGIN_NV04(push, NV50_3D(VIEWPORT_TRANSFORM_EN), 1);
PUSH_DATA (push, 1);
- BEGIN_NV04(push, NV50_3D(DEPTH_RANGE_NEAR(0)), 2);
- PUSH_DATAf(push, 0.0f);
- PUSH_DATAf(push, 1.0f);
+ for (i = 0; i < NV50_MAX_VIEWPORTS; i++) {
+ BEGIN_NV04(push, NV50_3D(DEPTH_RANGE_NEAR(i)), 2);
+ PUSH_DATAf(push, 0.0f);
+ PUSH_DATAf(push, 1.0f);
+ BEGIN_NV04(push, NV50_3D(VIEWPORT_HORIZ(i)), 2);
+ PUSH_DATA (push, 8192 << 16);
+ PUSH_DATA (push, 8192 << 16);
+ }
BEGIN_NV04(push, NV50_3D(VIEW_VOLUME_CLIP_CTRL), 1);
#ifdef NV50_SCISSORS_CLIPPING
/* We use scissors instead of exact view volume clipping,
* so they're always enabled.
*/
- BEGIN_NV04(push, NV50_3D(SCISSOR_ENABLE(0)), 3);
- PUSH_DATA (push, 1);
- PUSH_DATA (push, 8192 << 16);
- PUSH_DATA (push, 8192 << 16);
+ for (i = 0; i < NV50_MAX_VIEWPORTS; i++) {
+ BEGIN_NV04(push, NV50_3D(SCISSOR_ENABLE(i)), 3);
+ PUSH_DATA (push, 1);
+ PUSH_DATA (push, 8192 << 16);
+ PUSH_DATA (push, 8192 << 16);
+ }
BEGIN_NV04(push, NV50_3D(RASTERIZE_ENABLE), 1);
PUSH_DATA (push, 1);
int i, n, c, m;
uint32_t primid = 0;
uint32_t layerid = 0;
+ uint32_t viewportid = 0;
uint32_t psiz = 0x000;
uint32_t interp = fp->fp.interp;
uint32_t colors = fp->fp.colors;
case TGSI_SEMANTIC_LAYER:
layerid = m;
break;
+ case TGSI_SEMANTIC_VIEWPORT_INDEX:
+ viewportid = m;
+ break;
}
m = nv50_vec4_map(map, m, lin,
&fp->in[i], (n < vp->out_nr) ? &vp->out[n] : &dummy);
map[m++] = vp->gp.layerid;
}
+ if (vp->gp.has_viewport && !viewportid) {
+ viewportid = m;
+ map[m++] = vp->gp.viewportid;
+ }
+
if (nv50->rast->pipe.point_size_per_vertex) {
psiz = (m << 4) | 1;
map[m++] = vp->vp.psiz;
PUSH_DATAp(push, map, n);
}
- BEGIN_NV04(push, NV50_3D(SEMANTIC_COLOR), 4);
+ BEGIN_NV04(push, NV50_3D(GP_VIEWPORT_ID_ENABLE), 5);
+ PUSH_DATA (push, vp->gp.has_viewport);
PUSH_DATA (push, colors);
PUSH_DATA (push, (vp->vp.clpd_nr << 8) | 4);
PUSH_DATA (push, layerid);
PUSH_DATA (push, psiz);
+ BEGIN_NV04(push, NV50_3D(SEMANTIC_VIEWPORT), 1);
+ PUSH_DATA (push, viewportid);
+
BEGIN_NV04(push, NV50_3D(LAYER), 1);
PUSH_DATA (push, vp->gp.has_layer << 16);
so->pipe = *cso;
#ifndef NV50_SCISSORS_CLIPPING
- SB_BEGIN_3D(so, SCISSOR_ENABLE(0), 1);
- SB_DATA (so, cso->scissor);
+ for (int i = 0; i < NV50_MAX_VIEWPORTS; i++) {
+ SB_BEGIN_3D(so, SCISSOR_ENABLE(i), 1);
+ SB_DATA (so, cso->scissor);
+ }
#endif
SB_BEGIN_3D(so, SHADE_MODEL, 1);
const struct pipe_scissor_state *scissor)
{
struct nv50_context *nv50 = nv50_context(pipe);
+ int i;
- nv50->scissor = *scissor;
- nv50->dirty |= NV50_NEW_SCISSOR;
+ assert(start_slot + num_scissors <= NV50_MAX_VIEWPORTS);
+ for (i = 0; i < num_scissors; i++) {
+ if (!memcmp(&nv50->scissors[start_slot + i], &scissor[i], sizeof(*scissor)))
+ continue;
+ nv50->scissors[start_slot + i] = scissor[i];
+ nv50->scissors_dirty |= 1 << (start_slot + i);
+ nv50->dirty |= NV50_NEW_SCISSOR;
+ }
}
static void
const struct pipe_viewport_state *vpt)
{
struct nv50_context *nv50 = nv50_context(pipe);
+ int i;
- nv50->viewport = *vpt;
- nv50->dirty |= NV50_NEW_VIEWPORT;
+ assert(start_slot + num_viewports <= NV50_MAX_VIEWPORTS);
+ for (i = 0; i < num_viewports; i++) {
+ if (!memcmp(&nv50->viewports[start_slot + i], &vpt[i], sizeof(*vpt)))
+ continue;
+ nv50->viewports[start_slot + i] = vpt[i];
+ nv50->viewports_dirty |= 1 << (start_slot + i);
+ nv50->dirty |= NV50_NEW_VIEWPORT;
+ }
}
static void
BEGIN_NV04(push, NV50_3D(MULTISAMPLE_MODE), 1);
PUSH_DATA (push, ms_mode);
+ /* Only need to initialize the first viewport, which is used for clears */
BEGIN_NV04(push, NV50_3D(VIEWPORT_HORIZ(0)), 2);
PUSH_DATA (push, fb->width << 16);
PUSH_DATA (push, fb->height << 16);
nv50_validate_scissor(struct nv50_context *nv50)
{
struct nouveau_pushbuf *push = nv50->base.pushbuf;
- struct pipe_scissor_state *s = &nv50->scissor;
#ifdef NV50_SCISSORS_CLIPPING
- struct pipe_viewport_state *vp = &nv50->viewport;
- int minx, maxx, miny, maxy;
+ int minx, maxx, miny, maxy, i;
if (!(nv50->dirty &
(NV50_NEW_SCISSOR | NV50_NEW_VIEWPORT | NV50_NEW_FRAMEBUFFER)) &&
nv50->state.scissor == nv50->rast->pipe.scissor)
return;
+
+ if (nv50->state.scissor != nv50->rast->pipe.scissor)
+ nv50->scissors_dirty = (1 << NV50_MAX_VIEWPORTS) - 1;
+
nv50->state.scissor = nv50->rast->pipe.scissor;
- if (nv50->state.scissor) {
- minx = s->minx;
- maxx = s->maxx;
- miny = s->miny;
- maxy = s->maxy;
- } else {
- minx = 0;
- maxx = nv50->framebuffer.width;
- miny = 0;
- maxy = nv50->framebuffer.height;
- }
+ if ((nv50->dirty & NV50_NEW_FRAMEBUFFER) && !nv50->state.scissor)
+ nv50->scissors_dirty = (1 << NV50_MAX_VIEWPORTS) - 1;
+
+ for (i = 0; i < NV50_MAX_VIEWPORTS; i++) {
+ struct pipe_scissor_state *s = &nv50->scissors[i];
+ struct pipe_viewport_state *vp = &nv50->viewports[i];
+
+ if (!(nv50->scissors_dirty & (1 << i)) &&
+ !(nv50->viewports_dirty & (1 << i)))
+ continue;
+
+ if (nv50->state.scissor) {
+ minx = s->minx;
+ maxx = s->maxx;
+ miny = s->miny;
+ maxy = s->maxy;
+ } else {
+ minx = 0;
+ maxx = nv50->framebuffer.width;
+ miny = 0;
+ maxy = nv50->framebuffer.height;
+ }
+
+ minx = MAX2(minx, (int)(vp->translate[0] - fabsf(vp->scale[0])));
+ maxx = MIN2(maxx, (int)(vp->translate[0] + fabsf(vp->scale[0])));
+ miny = MAX2(miny, (int)(vp->translate[1] - fabsf(vp->scale[1])));
+ maxy = MIN2(maxy, (int)(vp->translate[1] + fabsf(vp->scale[1])));
- minx = MAX2(minx, (int)(vp->translate[0] - fabsf(vp->scale[0])));
- maxx = MIN2(maxx, (int)(vp->translate[0] + fabsf(vp->scale[0])));
- miny = MAX2(miny, (int)(vp->translate[1] - fabsf(vp->scale[1])));
- maxy = MIN2(maxy, (int)(vp->translate[1] + fabsf(vp->scale[1])));
+ minx = MIN2(minx, 8192);
+ maxx = MAX2(maxx, 0);
+ miny = MIN2(miny, 8192);
+ maxy = MAX2(maxy, 0);
- BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(0)), 2);
- PUSH_DATA (push, (maxx << 16) | minx);
- PUSH_DATA (push, (maxy << 16) | miny);
+ BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(i)), 2);
+ PUSH_DATA (push, (maxx << 16) | minx);
+ PUSH_DATA (push, (maxy << 16) | miny);
#else
- BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(0)), 2);
- PUSH_DATA (push, (s->maxx << 16) | s->minx);
- PUSH_DATA (push, (s->maxy << 16) | s->miny);
+ BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(i)), 2);
+ PUSH_DATA (push, (s->maxx << 16) | s->minx);
+ PUSH_DATA (push, (s->maxy << 16) | s->miny);
#endif
+ }
+
+ nv50->scissors_dirty = 0;
}
static void
{
struct nouveau_pushbuf *push = nv50->base.pushbuf;
float zmin, zmax;
+ int i;
- BEGIN_NV04(push, NV50_3D(VIEWPORT_TRANSLATE_X(0)), 3);
- PUSH_DATAf(push, nv50->viewport.translate[0]);
- PUSH_DATAf(push, nv50->viewport.translate[1]);
- PUSH_DATAf(push, nv50->viewport.translate[2]);
- BEGIN_NV04(push, NV50_3D(VIEWPORT_SCALE_X(0)), 3);
- PUSH_DATAf(push, nv50->viewport.scale[0]);
- PUSH_DATAf(push, nv50->viewport.scale[1]);
- PUSH_DATAf(push, nv50->viewport.scale[2]);
+ for (i = 0; i < NV50_MAX_VIEWPORTS; i++) {
+ struct pipe_viewport_state *vpt = &nv50->viewports[i];
- zmin = nv50->viewport.translate[2] - fabsf(nv50->viewport.scale[2]);
- zmax = nv50->viewport.translate[2] + fabsf(nv50->viewport.scale[2]);
+ if (!(nv50->viewports_dirty & (1 << i)))
+ continue;
+
+ BEGIN_NV04(push, NV50_3D(VIEWPORT_TRANSLATE_X(i)), 3);
+ PUSH_DATAf(push, vpt->translate[0]);
+ PUSH_DATAf(push, vpt->translate[1]);
+ PUSH_DATAf(push, vpt->translate[2]);
+ BEGIN_NV04(push, NV50_3D(VIEWPORT_SCALE_X(i)), 3);
+ PUSH_DATAf(push, vpt->scale[0]);
+ PUSH_DATAf(push, vpt->scale[1]);
+ PUSH_DATAf(push, vpt->scale[2]);
+
+ zmin = vpt->translate[2] - fabsf(vpt->scale[2]);
+ zmax = vpt->translate[2] + fabsf(vpt->scale[2]);
#ifdef NV50_SCISSORS_CLIPPING
- BEGIN_NV04(push, NV50_3D(DEPTH_RANGE_NEAR(0)), 2);
- PUSH_DATAf(push, zmin);
- PUSH_DATAf(push, zmax);
+ BEGIN_NV04(push, NV50_3D(DEPTH_RANGE_NEAR(i)), 2);
+ PUSH_DATAf(push, zmin);
+ PUSH_DATAf(push, zmax);
#endif
+ }
+
+ nv50->viewports_dirty = 0;
}
static INLINE void