blob: 932848ea94be98d7fc6a9a9d4ecf72b95dc39e40 [file] [log] [blame]
/*
* Copyright 2010 Christoph Bumiller
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_state.h"
#include "util/u_inlines.h"
#include "nvc0_context.h"
static boolean
nvc0_program_validate(struct nvc0_context *nvc0, struct nvc0_program *prog)
{
int ret;
unsigned size;
if (prog->translated)
return TRUE;
prog->translated = nvc0_program_translate(prog);
if (!prog->translated)
return FALSE;
size = align(prog->code_size + NVC0_SHADER_HEADER_SIZE, 0x100);
ret = nouveau_resource_alloc(nvc0->screen->text_heap, size, prog,
&prog->res);
if (ret)
return FALSE;
prog->code_base = prog->res->start;
nvc0_m2mf_push_linear(nvc0, nvc0->screen->text, NOUVEAU_BO_VRAM,
prog->code_base, NVC0_SHADER_HEADER_SIZE, prog->hdr);
nvc0_m2mf_push_linear(nvc0, nvc0->screen->text, NOUVEAU_BO_VRAM,
prog->code_base + NVC0_SHADER_HEADER_SIZE,
prog->code_size, prog->code);
BEGIN_RING(nvc0->screen->base.channel, RING_3D_(0x021c), 1);
OUT_RING (nvc0->screen->base.channel, 0x1111);
return TRUE;
}
void
nvc0_vertprog_validate(struct nvc0_context *nvc0)
{
struct nouveau_channel *chan = nvc0->screen->base.channel;
struct nvc0_program *vp = nvc0->vertprog;
if (!nvc0_program_validate(nvc0, vp))
return;
BEGIN_RING(chan, RING_3D(SP_SELECT(1)), 2);
OUT_RING (chan, 0x11);
OUT_RING (chan, vp->code_base);
BEGIN_RING(chan, RING_3D(SP_GPR_ALLOC(1)), 1);
OUT_RING (chan, vp->max_gpr);
BEGIN_RING(chan, RING_3D_(0x163c), 1);
OUT_RING (chan, 0);
BEGIN_RING(chan, RING_3D_(0x2600), 1);
OUT_RING (chan, 1);
}
void
nvc0_fragprog_validate(struct nvc0_context *nvc0)
{
struct nouveau_channel *chan = nvc0->screen->base.channel;
struct nvc0_program *fp = nvc0->fragprog;
if (!nvc0_program_validate(nvc0, fp))
return;
BEGIN_RING(chan, RING_3D(EARLY_FRAGMENT_TESTS), 1);
OUT_RING (chan, 0);
BEGIN_RING(chan, RING_3D(SP_SELECT(5)), 2);
OUT_RING (chan, 0x51);
OUT_RING (chan, fp->code_base);
BEGIN_RING(chan, RING_3D(SP_GPR_ALLOC(5)), 1);
OUT_RING (chan, fp->max_gpr);
BEGIN_RING(chan, RING_3D_(0x0360), 2);
OUT_RING (chan, 0x20164010);
OUT_RING (chan, 0x20);
BEGIN_RING(chan, RING_3D_(0x196c), 1);
OUT_RING (chan, fp->flags[0]);
}
void
nvc0_tctlprog_validate(struct nvc0_context *nvc0)
{
struct nouveau_channel *chan = nvc0->screen->base.channel;
struct nvc0_program *tp = nvc0->tctlprog;
if (!tp) {
BEGIN_RING(chan, RING_3D(SP_SELECT(2)), 1);
OUT_RING (chan, 0x20);
return;
}
if (!nvc0_program_validate(nvc0, tp))
return;
BEGIN_RING(chan, RING_3D(SP_SELECT(2)), 2);
OUT_RING (chan, 0x21);
OUT_RING (chan, tp->code_base);
BEGIN_RING(chan, RING_3D(SP_GPR_ALLOC(2)), 1);
OUT_RING (chan, tp->max_gpr);
}
void
nvc0_tevlprog_validate(struct nvc0_context *nvc0)
{
struct nouveau_channel *chan = nvc0->screen->base.channel;
struct nvc0_program *tp = nvc0->tevlprog;
if (!tp) {
BEGIN_RING(chan, RING_3D(TEP_SELECT), 1);
OUT_RING (chan, 0x30);
return;
}
if (!nvc0_program_validate(nvc0, tp))
return;
BEGIN_RING(chan, RING_3D(TEP_SELECT), 1);
OUT_RING (chan, 0x31);
BEGIN_RING(chan, RING_3D(SP_START_ID(3)), 1);
OUT_RING (chan, tp->code_base);
BEGIN_RING(chan, RING_3D(SP_GPR_ALLOC(3)), 1);
OUT_RING (chan, tp->max_gpr);
}
void
nvc0_gmtyprog_validate(struct nvc0_context *nvc0)
{
struct nouveau_channel *chan = nvc0->screen->base.channel;
struct nvc0_program *gp = nvc0->gmtyprog;
if (!gp) {
BEGIN_RING(chan, RING_3D(GP_SELECT), 1);
OUT_RING (chan, 0x40);
return;
}
if (!nvc0_program_validate(nvc0, gp))
return;
BEGIN_RING(chan, RING_3D(GP_SELECT), 1);
OUT_RING (chan, 0x41);
BEGIN_RING(chan, RING_3D(SP_START_ID(4)), 1);
OUT_RING (chan, gp->code_base);
BEGIN_RING(chan, RING_3D(SP_GPR_ALLOC(4)), 1);
OUT_RING (chan, gp->max_gpr);
}