summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/nv30
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/nv30')
-rw-r--r--src/gallium/drivers/nv30/nv30_context.c24
-rw-r--r--src/gallium/drivers/nv30/nv30_context.h10
-rw-r--r--src/gallium/drivers/nv30/nv30_fragprog.c122
-rw-r--r--src/gallium/drivers/nv30/nv30_fragtex.c14
-rw-r--r--src/gallium/drivers/nv30/nv30_miptree.c62
-rw-r--r--src/gallium/drivers/nv30/nv30_query.c20
-rw-r--r--src/gallium/drivers/nv30/nv30_screen.c12
-rw-r--r--src/gallium/drivers/nv30/nv30_state.c21
-rw-r--r--src/gallium/drivers/nv30/nv30_state.h1
-rw-r--r--src/gallium/drivers/nv30/nv30_state_blend.c2
-rw-r--r--src/gallium/drivers/nv30/nv30_state_emit.c10
-rw-r--r--src/gallium/drivers/nv30/nv30_state_fb.c2
-rw-r--r--src/gallium/drivers/nv30/nv30_state_scissor.c2
-rw-r--r--src/gallium/drivers/nv30/nv30_state_stipple.c4
-rw-r--r--src/gallium/drivers/nv30/nv30_state_viewport.c2
-rw-r--r--src/gallium/drivers/nv30/nv30_transfer.c39
-rw-r--r--src/gallium/drivers/nv30/nv30_vbo.c133
-rw-r--r--src/gallium/drivers/nv30/nv30_vertprog.c91
18 files changed, 319 insertions, 252 deletions
diff --git a/src/gallium/drivers/nv30/nv30_context.c b/src/gallium/drivers/nv30/nv30_context.c
index d8300fd69f..54572e9ab3 100644
--- a/src/gallium/drivers/nv30/nv30_context.c
+++ b/src/gallium/drivers/nv30/nv30_context.c
@@ -10,21 +10,32 @@ nv30_flush(struct pipe_context *pipe, unsigned flags,
struct pipe_fence_handle **fence)
{
struct nv30_context *nv30 = nv30_context(pipe);
+ struct nv30_screen *screen = nv30->screen;
+ struct nouveau_channel *chan = screen->base.channel;
+ struct nouveau_grobj *rankine = screen->rankine;
if (flags & PIPE_FLUSH_TEXTURE_CACHE) {
- BEGIN_RING(rankine, 0x1fd8, 1);
- OUT_RING (2);
- BEGIN_RING(rankine, 0x1fd8, 1);
- OUT_RING (1);
+ BEGIN_RING(chan, rankine, 0x1fd8, 1);
+ OUT_RING (chan, 2);
+ BEGIN_RING(chan, rankine, 0x1fd8, 1);
+ OUT_RING (chan, 1);
}
- FIRE_RING(fence);
+ FIRE_RING(chan);
+ if (fence)
+ *fence = NULL;
}
static void
nv30_destroy(struct pipe_context *pipe)
{
struct nv30_context *nv30 = nv30_context(pipe);
+ unsigned i;
+
+ for (i = 0; i < NV30_STATE_MAX; i++) {
+ if (nv30->state.hw[i])
+ so_ref(NULL, &nv30->state.hw[i]);
+ }
if (nv30->draw)
draw_destroy(nv30->draw);
@@ -58,6 +69,9 @@ nv30_create(struct pipe_screen *pscreen, unsigned pctx_id)
nv30->pipe.is_texture_referenced = nouveau_is_texture_referenced;
nv30->pipe.is_buffer_referenced = nouveau_is_buffer_referenced;
+ screen->base.channel->user_private = nv30;
+ screen->base.channel->flush_notify = nv30_state_flush_notify;
+
nv30_init_query_functions(nv30);
nv30_init_surface_functions(nv30);
nv30_init_state_functions(nv30);
diff --git a/src/gallium/drivers/nv30/nv30_context.h b/src/gallium/drivers/nv30/nv30_context.h
index 8d49366dfc..e59449287b 100644
--- a/src/gallium/drivers/nv30/nv30_context.h
+++ b/src/gallium/drivers/nv30/nv30_context.h
@@ -14,10 +14,6 @@
#include "nouveau/nouveau_winsys.h"
#include "nouveau/nouveau_gldefs.h"
#include "nouveau/nouveau_context.h"
-
-#define NOUVEAU_PUSH_CONTEXT(ctx) \
- struct nv30_screen *ctx = nv30->screen
-#include "nouveau/nouveau_push.h"
#include "nouveau/nouveau_stateobj.h"
#include "nv30_state.h"
@@ -144,7 +140,6 @@ struct nv30_context {
unsigned vtxbuf_nr;
struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS];
unsigned vtxelt_nr;
- const unsigned *edgeflags;
};
static INLINE struct nv30_context *
@@ -184,6 +179,7 @@ extern void nv30_fragtex_bind(struct nv30_context *);
/* nv30_state.c and friends */
extern boolean nv30_state_validate(struct nv30_context *nv30);
extern void nv30_state_emit(struct nv30_context *nv30);
+extern void nv30_state_flush_notify(struct nouveau_channel *chan);
extern struct nv30_state_entry nv30_state_rasterizer;
extern struct nv30_state_entry nv30_state_scissor;
extern struct nv30_state_entry nv30_state_stipple;
@@ -198,9 +194,9 @@ extern struct nv30_state_entry nv30_state_fragtex;
extern struct nv30_state_entry nv30_state_vbo;
/* nv30_vbo.c */
-extern boolean nv30_draw_arrays(struct pipe_context *, unsigned mode,
+extern void nv30_draw_arrays(struct pipe_context *, unsigned mode,
unsigned start, unsigned count);
-extern boolean nv30_draw_elements(struct pipe_context *pipe,
+extern void nv30_draw_elements(struct pipe_context *pipe,
struct pipe_buffer *indexBuffer,
unsigned indexSize,
unsigned mode, unsigned start,
diff --git a/src/gallium/drivers/nv30/nv30_fragprog.c b/src/gallium/drivers/nv30/nv30_fragprog.c
index 0ce702d6f8..2d565cb631 100644
--- a/src/gallium/drivers/nv30/nv30_fragprog.c
+++ b/src/gallium/drivers/nv30/nv30_fragprog.c
@@ -237,20 +237,20 @@ tgsi_src(struct nv30_fpc *fpc, const struct tgsi_full_src_register *fsrc)
{
struct nv30_sreg src;
- switch (fsrc->SrcRegister.File) {
+ switch (fsrc->Register.File) {
case TGSI_FILE_INPUT:
src = nv30_sr(NV30SR_INPUT,
- fpc->attrib_map[fsrc->SrcRegister.Index]);
+ fpc->attrib_map[fsrc->Register.Index]);
break;
case TGSI_FILE_CONSTANT:
- src = constant(fpc, fsrc->SrcRegister.Index, NULL);
+ src = constant(fpc, fsrc->Register.Index, NULL);
break;
case TGSI_FILE_IMMEDIATE:
- assert(fsrc->SrcRegister.Index < fpc->nr_imm);
- src = fpc->imm[fsrc->SrcRegister.Index];
+ assert(fsrc->Register.Index < fpc->nr_imm);
+ src = fpc->imm[fsrc->Register.Index];
break;
case TGSI_FILE_TEMPORARY:
- src = nv30_sr(NV30SR_TEMP, fsrc->SrcRegister.Index + 1);
+ src = nv30_sr(NV30SR_TEMP, fsrc->Register.Index + 1);
if (fpc->high_temp < src.index)
fpc->high_temp = src.index;
break;
@@ -258,7 +258,7 @@ tgsi_src(struct nv30_fpc *fpc, const struct tgsi_full_src_register *fsrc)
* Luckily fragprog results are just temp regs..
*/
case TGSI_FILE_OUTPUT:
- if (fsrc->SrcRegister.Index == fpc->colour_id)
+ if (fsrc->Register.Index == fpc->colour_id)
return nv30_sr(NV30SR_OUTPUT, 0);
else
return nv30_sr(NV30SR_OUTPUT, 1);
@@ -268,12 +268,12 @@ tgsi_src(struct nv30_fpc *fpc, const struct tgsi_full_src_register *fsrc)
break;
}
- src.abs = fsrc->SrcRegisterExtMod.Absolute;
- src.negate = fsrc->SrcRegister.Negate;
- src.swz[0] = fsrc->SrcRegister.SwizzleX;
- src.swz[1] = fsrc->SrcRegister.SwizzleY;
- src.swz[2] = fsrc->SrcRegister.SwizzleZ;
- src.swz[3] = fsrc->SrcRegister.SwizzleW;
+ src.abs = fsrc->Register.Absolute;
+ src.negate = fsrc->Register.Negate;
+ src.swz[0] = fsrc->Register.SwizzleX;
+ src.swz[1] = fsrc->Register.SwizzleY;
+ src.swz[2] = fsrc->Register.SwizzleZ;
+ src.swz[3] = fsrc->Register.SwizzleW;
return src;
}
@@ -281,22 +281,22 @@ static INLINE struct nv30_sreg
tgsi_dst(struct nv30_fpc *fpc, const struct tgsi_full_dst_register *fdst) {
int idx;
- switch (fdst->DstRegister.File) {
+ switch (fdst->Register.File) {
case TGSI_FILE_OUTPUT:
- if (fdst->DstRegister.Index == fpc->colour_id)
+ if (fdst->Register.Index == fpc->colour_id)
return nv30_sr(NV30SR_OUTPUT, 0);
else
return nv30_sr(NV30SR_OUTPUT, 1);
break;
case TGSI_FILE_TEMPORARY:
- idx = fdst->DstRegister.Index + 1;
+ idx = fdst->Register.Index + 1;
if (fpc->high_temp < idx)
fpc->high_temp = idx;
return nv30_sr(NV30SR_TEMP, idx);
case TGSI_FILE_NULL:
return nv30_sr(NV30SR_NONE, 0);
default:
- NOUVEAU_ERR("bad dst file %d\n", fdst->DstRegister.File);
+ NOUVEAU_ERR("bad dst file %d\n", fdst->Register.File);
return nv30_sr(NV30SR_NONE, 0);
}
}
@@ -363,8 +363,8 @@ nv30_fragprog_parse_instruction(struct nv30_fpc *fpc,
for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
const struct tgsi_full_src_register *fsrc;
- fsrc = &finst->FullSrcRegisters[i];
- if (fsrc->SrcRegister.File == TGSI_FILE_TEMPORARY) {
+ fsrc = &finst->Src[i];
+ if (fsrc->Register.File == TGSI_FILE_TEMPORARY) {
src[i] = tgsi_src(fpc, fsrc);
}
}
@@ -372,9 +372,9 @@ nv30_fragprog_parse_instruction(struct nv30_fpc *fpc,
for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
const struct tgsi_full_src_register *fsrc;
- fsrc = &finst->FullSrcRegisters[i];
+ fsrc = &finst->Src[i];
- switch (fsrc->SrcRegister.File) {
+ switch (fsrc->Register.File) {
case TGSI_FILE_INPUT:
case TGSI_FILE_CONSTANT:
case TGSI_FILE_TEMPORARY:
@@ -385,14 +385,14 @@ nv30_fragprog_parse_instruction(struct nv30_fpc *fpc,
break;
}
- switch (fsrc->SrcRegister.File) {
+ switch (fsrc->Register.File) {
case TGSI_FILE_INPUT:
- if (ai == -1 || ai == fsrc->SrcRegister.Index) {
- ai = fsrc->SrcRegister.Index;
+ if (ai == -1 || ai == fsrc->Register.Index) {
+ ai = fsrc->Register.Index;
src[i] = tgsi_src(fpc, fsrc);
} else {
NOUVEAU_MSG("extra src attr %d\n",
- fsrc->SrcRegister.Index);
+ fsrc->Register.Index);
src[i] = temp(fpc);
arith(fpc, 0, MOV, src[i], MASK_ALL,
tgsi_src(fpc, fsrc), none, none);
@@ -400,8 +400,8 @@ nv30_fragprog_parse_instruction(struct nv30_fpc *fpc,
break;
case TGSI_FILE_CONSTANT:
case TGSI_FILE_IMMEDIATE:
- if (ci == -1 || ci == fsrc->SrcRegister.Index) {
- ci = fsrc->SrcRegister.Index;
+ if (ci == -1 || ci == fsrc->Register.Index) {
+ ci = fsrc->Register.Index;
src[i] = tgsi_src(fpc, fsrc);
} else {
src[i] = temp(fpc);
@@ -413,7 +413,7 @@ nv30_fragprog_parse_instruction(struct nv30_fpc *fpc,
/* handled above */
break;
case TGSI_FILE_SAMPLER:
- unit = fsrc->SrcRegister.Index;
+ unit = fsrc->Register.Index;
break;
case TGSI_FILE_OUTPUT:
break;
@@ -423,8 +423,8 @@ nv30_fragprog_parse_instruction(struct nv30_fpc *fpc,
}
}
- dst = tgsi_dst(fpc, &finst->FullDstRegisters[0]);
- mask = tgsi_mask(finst->FullDstRegisters[0].DstRegister.WriteMask);
+ dst = tgsi_dst(fpc, &finst->Dst[0]);
+ mask = tgsi_mask(finst->Dst[0].Register.WriteMask);
sat = (finst->Instruction.Saturate == TGSI_SAT_ZERO_ONE);
switch (finst->Instruction.Opcode) {
@@ -435,10 +435,11 @@ nv30_fragprog_parse_instruction(struct nv30_fpc *fpc,
arith(fpc, sat, ADD, dst, mask, src[0], src[1], none);
break;
case TGSI_OPCODE_CMP:
- tmp = temp(fpc);
- arith(fpc, sat, MOV, dst, mask, src[2], none, none);
+ tmp = nv30_sr(NV30SR_NONE, 0);
tmp.cc_update = 1;
arith(fpc, 0, MOV, tmp, 0xf, src[0], none, none);
+ dst.cc_test = NV30_VP_INST_COND_GE;
+ arith(fpc, sat, MOV, dst, mask, src[2], none, none);
dst.cc_test = NV30_VP_INST_COND_LT;
arith(fpc, sat, MOV, dst, mask, src[1], none, none);
break;
@@ -517,13 +518,28 @@ nv30_fragprog_parse_instruction(struct nv30_fpc *fpc,
arith(fpc, sat, RSQ, dst, mask, abs(swz(src[0], X, X, X, X)), none, none);
break;
case TGSI_OPCODE_SCS:
- if (mask & MASK_X) {
- arith(fpc, sat, COS, dst, MASK_X,
- swz(src[0], X, X, X, X), none, none);
+ /* avoid overwriting the source */
+ if(src[0].swz[SWZ_X] != SWZ_X)
+ {
+ if (mask & MASK_X) {
+ arith(fpc, sat, COS, dst, MASK_X,
+ swz(src[0], X, X, X, X), none, none);
+ }
+ if (mask & MASK_Y) {
+ arith(fpc, sat, SIN, dst, MASK_Y,
+ swz(src[0], X, X, X, X), none, none);
+ }
}
- if (mask & MASK_Y) {
- arith(fpc, sat, SIN, dst, MASK_Y,
- swz(src[0], X, X, X, X), none, none);
+ else
+ {
+ if (mask & MASK_Y) {
+ arith(fpc, sat, SIN, dst, MASK_Y,
+ swz(src[0], X, X, X, X), none, none);
+ }
+ if (mask & MASK_X) {
+ arith(fpc, sat, COS, dst, MASK_X,
+ swz(src[0], X, X, X, X), none, none);
+ }
}
break;
case TGSI_OPCODE_SIN:
@@ -572,15 +588,15 @@ nv30_fragprog_parse_decl_attrib(struct nv30_fpc *fpc,
{
int hw;
- switch (fdec->Semantic.SemanticName) {
+ switch (fdec->Semantic.Name) {
case TGSI_SEMANTIC_POSITION:
hw = NV30_FP_OP_INPUT_SRC_POSITION;
break;
case TGSI_SEMANTIC_COLOR:
- if (fdec->Semantic.SemanticIndex == 0) {
+ if (fdec->Semantic.Index == 0) {
hw = NV30_FP_OP_INPUT_SRC_COL0;
} else
- if (fdec->Semantic.SemanticIndex == 1) {
+ if (fdec->Semantic.Index == 1) {
hw = NV30_FP_OP_INPUT_SRC_COL1;
} else {
NOUVEAU_ERR("bad colour semantic index\n");
@@ -591,9 +607,9 @@ nv30_fragprog_parse_decl_attrib(struct nv30_fpc *fpc,
hw = NV30_FP_OP_INPUT_SRC_FOGC;
break;
case TGSI_SEMANTIC_GENERIC:
- if (fdec->Semantic.SemanticIndex <= 7) {
+ if (fdec->Semantic.Index <= 7) {
hw = NV30_FP_OP_INPUT_SRC_TC(fdec->Semantic.
- SemanticIndex);
+ Index);
} else {
NOUVEAU_ERR("bad generic semantic index\n");
return FALSE;
@@ -604,7 +620,7 @@ nv30_fragprog_parse_decl_attrib(struct nv30_fpc *fpc,
return FALSE;
}
- fpc->attrib_map[fdec->DeclarationRange.First] = hw;
+ fpc->attrib_map[fdec->Range.First] = hw;
return TRUE;
}
@@ -612,12 +628,12 @@ static boolean
nv30_fragprog_parse_decl_output(struct nv30_fpc *fpc,
const struct tgsi_full_declaration *fdec)
{
- switch (fdec->Semantic.SemanticName) {
+ switch (fdec->Semantic.Name) {
case TGSI_SEMANTIC_POSITION:
- fpc->depth_id = fdec->DeclarationRange.First;
+ fpc->depth_id = fdec->Range.First;
break;
case TGSI_SEMANTIC_COLOR:
- fpc->colour_id = fdec->DeclarationRange.First;
+ fpc->colour_id = fdec->Range.First;
break;
default:
NOUVEAU_ERR("bad output semantic\n");
@@ -653,9 +669,9 @@ nv30_fragprog_prepare(struct nv30_fpc *fpc)
goto out_err;
break;
/*case TGSI_FILE_TEMPORARY:
- if (fdec->DeclarationRange.Last > high_temp) {
+ if (fdec->Range.Last > high_temp) {
high_temp =
- fdec->DeclarationRange.Last;
+ fdec->Range.Last;
}
break;*/
default:
@@ -821,7 +837,7 @@ nv30_fragprog_validate(struct nv30_context *nv30)
fp->buffer = pscreen->buffer_create(pscreen, 0x100, 0, fp->insn_len * 4);
nv30_fragprog_upload(nv30, fp);
- so = so_new(8, 1);
+ so = so_new(4, 4, 1);
so_method(so, nv30->screen->rankine, NV34TCL_FP_ACTIVE_PROGRAM, 1);
so_reloc (so, nouveau_bo(fp->buffer), 0, NOUVEAU_BO_VRAM |
NOUVEAU_BO_GART | NOUVEAU_BO_RD | NOUVEAU_BO_LOW |
@@ -870,6 +886,12 @@ void
nv30_fragprog_destroy(struct nv30_context *nv30,
struct nv30_fragment_program *fp)
{
+ if (fp->buffer)
+ pipe_buffer_reference(&fp->buffer, NULL);
+
+ if (fp->so)
+ so_ref(NULL, &fp->so);
+
if (fp->insn_len)
FREE(fp->insn);
}
diff --git a/src/gallium/drivers/nv30/nv30_fragtex.c b/src/gallium/drivers/nv30/nv30_fragtex.c
index dca760cae6..9893567891 100644
--- a/src/gallium/drivers/nv30/nv30_fragtex.c
+++ b/src/gallium/drivers/nv30/nv30_fragtex.c
@@ -74,9 +74,9 @@ nv30_fragtex_build(struct nv30_context *nv30, int unit)
txf = tf->format;
txf |= ((pt->last_level>0) ? NV34TCL_TX_FORMAT_MIPMAP : 0);
- txf |= log2i(pt->width[0]) << NV34TCL_TX_FORMAT_BASE_SIZE_U_SHIFT;
- txf |= log2i(pt->height[0]) << NV34TCL_TX_FORMAT_BASE_SIZE_V_SHIFT;
- txf |= log2i(pt->depth[0]) << NV34TCL_TX_FORMAT_BASE_SIZE_W_SHIFT;
+ txf |= log2i(pt->width0) << NV34TCL_TX_FORMAT_BASE_SIZE_U_SHIFT;
+ txf |= log2i(pt->height0) << NV34TCL_TX_FORMAT_BASE_SIZE_V_SHIFT;
+ txf |= log2i(pt->depth0) << NV34TCL_TX_FORMAT_BASE_SIZE_W_SHIFT;
txf |= NV34TCL_TX_FORMAT_NO_BORDER | 0x10000;
switch (pt->target) {
@@ -106,7 +106,7 @@ nv30_fragtex_build(struct nv30_context *nv30, int unit)
txs = tf->swizzle;
- so = so_new(16, 2);
+ so = so_new(1, 8, 2);
so_method(so, nv30->screen->rankine, NV34TCL_TX_OFFSET(unit), 8);
so_reloc (so, bo, 0, tex_flags | NOUVEAU_BO_LOW, 0, 0);
so_reloc (so, bo, txf, tex_flags | NOUVEAU_BO_OR,
@@ -115,8 +115,8 @@ nv30_fragtex_build(struct nv30_context *nv30, int unit)
so_data (so, NV34TCL_TX_ENABLE_ENABLE | ps->en);
so_data (so, txs);
so_data (so, ps->filt | 0x2000 /*voodoo*/);
- so_data (so, (pt->width[0] << NV34TCL_TX_NPOT_SIZE_W_SHIFT) |
- pt->height[0]);
+ so_data (so, (pt->width0 << NV34TCL_TX_NPOT_SIZE_W_SHIFT) |
+ pt->height0);
so_data (so, ps->bcol);
return so;
@@ -135,7 +135,7 @@ nv30_fragtex_validate(struct nv30_context *nv30)
unit = ffs(samplers) - 1;
samplers &= ~(1 << unit);
- so = so_new(2, 0);
+ so = so_new(1, 1, 0);
so_method(so, nv30->screen->rankine, NV34TCL_TX_ENABLE(unit), 1);
so_data (so, 0);
so_ref(so, &nv30->state.hw[NV30_STATE_FRAGTEX0 + unit]);
diff --git a/src/gallium/drivers/nv30/nv30_miptree.c b/src/gallium/drivers/nv30/nv30_miptree.c
index 280696d450..8fbba38e78 100644
--- a/src/gallium/drivers/nv30/nv30_miptree.c
+++ b/src/gallium/drivers/nv30/nv30_miptree.c
@@ -1,14 +1,17 @@
#include "pipe/p_state.h"
#include "pipe/p_defines.h"
#include "pipe/p_inlines.h"
+#include "util/u_format.h"
+#include "util/u_math.h"
#include "nv30_context.h"
+#include "../nv04/nv04_surface_2d.h"
static void
nv30_miptree_layout(struct nv30_miptree *nv30mt)
{
struct pipe_texture *pt = &nv30mt->base;
- uint width = pt->width[0], height = pt->height[0], depth = pt->depth[0];
+ uint width = pt->width0;
uint offset = 0;
int nr_faces, l, f;
uint wide_pitch = pt->tex_usage & (PIPE_TEXTURE_USAGE_SAMPLER |
@@ -21,29 +24,21 @@ nv30_miptree_layout(struct nv30_miptree *nv30mt)
nr_faces = 6;
} else
if (pt->target == PIPE_TEXTURE_3D) {
- nr_faces = pt->depth[0];
+ nr_faces = pt->depth0;
} else {
nr_faces = 1;
}
for (l = 0; l <= pt->last_level; l++) {
- pt->width[l] = width;
- pt->height[l] = height;
- pt->depth[l] = depth;
- pt->nblocksx[l] = pf_get_nblocksx(&pt->block, width);
- pt->nblocksy[l] = pf_get_nblocksy(&pt->block, height);
-
if (wide_pitch && (pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR))
- nv30mt->level[l].pitch = align(pt->width[0] * pt->block.size, 64);
+ nv30mt->level[l].pitch = align(util_format_get_stride(pt->format, pt->width0), 64);
else
- nv30mt->level[l].pitch = pt->width[l] * pt->block.size;
+ nv30mt->level[l].pitch = util_format_get_stride(pt->format, width);
nv30mt->level[l].image_offset =
CALLOC(nr_faces, sizeof(unsigned));
- width = MAX2(1, width >> 1);
- height = MAX2(1, height >> 1);
- depth = MAX2(1, depth >> 1);
+ width = u_minify(width, 1);
}
for (f = 0; f < nr_faces; f++) {
@@ -51,14 +46,14 @@ nv30_miptree_layout(struct nv30_miptree *nv30mt)
nv30mt->level[l].image_offset[f] = offset;
if (!(pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR) &&
- pt->width[l + 1] > 1 && pt->height[l + 1] > 1)
- offset += align(nv30mt->level[l].pitch * pt->height[l], 64);
+ u_minify(pt->width0, l + 1) > 1 && u_minify(pt->height0, l + 1) > 1)
+ offset += align(nv30mt->level[l].pitch * u_minify(pt->height0, l), 64);
else
- offset += nv30mt->level[l].pitch * pt->height[l];
+ offset += nv30mt->level[l].pitch * u_minify(pt->height0, l);
}
nv30mt->level[l].image_offset[f] = offset;
- offset += nv30mt->level[l].pitch * pt->height[l];
+ offset += nv30mt->level[l].pitch * u_minify(pt->height0, l);
}
nv30mt->total_size = offset;
@@ -79,8 +74,8 @@ nv30_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt)
mt->base.screen = pscreen;
/* Swizzled textures must be POT */
- if (pt->width[0] & (pt->width[0] - 1) ||
- pt->height[0] & (pt->height[0] - 1))
+ if (pt->width0 & (pt->width0 - 1) ||
+ pt->height0 & (pt->height0 - 1))
mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR;
else
if (pt->tex_usage & (PIPE_TEXTURE_USAGE_PRIMARY |
@@ -114,6 +109,12 @@ nv30_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt)
if (pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC)
buf_usage |= PIPE_BUFFER_USAGE_CPU_READ_WRITE;
+ /* apparently we can't render to swizzled surfaces smaller than 64 bytes, so make them linear.
+ * If the user did not ask for a render target, they can still render to it, but it will cost them an extra copy.
+ * This also happens for small mipmaps of large textures. */
+ if (pt->tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET && util_format_get_stride(pt->format, pt->width0) < 64)
+ mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR;
+
nv30_miptree_layout(mt);
mt->buffer = pscreen->buffer_create(pscreen, 256, buf_usage,
@@ -122,6 +123,7 @@ nv30_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt)
FREE(mt);
return NULL;
}
+ mt->bo = nouveau_bo(mt->buffer);
return &mt->base;
}
@@ -134,7 +136,7 @@ nv30_miptree_blanket(struct pipe_screen *pscreen, const struct pipe_texture *pt,
/* Only supports 2D, non-mipmapped textures for the moment */
if (pt->target != PIPE_TEXTURE_2D || pt->last_level != 0 ||
- pt->depth[0] != 1)
+ pt->depth0 != 1)
return NULL;
mt = CALLOC_STRUCT(nv30_miptree);
@@ -151,6 +153,7 @@ nv30_miptree_blanket(struct pipe_screen *pscreen, const struct pipe_texture *pt,
mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR;
pipe_buffer_reference(&mt->buffer, pb);
+ mt->bo = nouveau_bo(mt->buffer);
return &mt->base;
}
@@ -182,8 +185,8 @@ nv30_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
return NULL;
pipe_texture_reference(&ns->base.texture, pt);
ns->base.format = pt->format;
- ns->base.width = pt->width[level];
- ns->base.height = pt->height[level];
+ ns->base.width = u_minify(pt->width0, level);
+ ns->base.height = u_minify(pt->height0, level);
ns->base.usage = flags;
pipe_reference_init(&ns->base.reference, 1);
ns->base.face = face;
@@ -200,12 +203,27 @@ nv30_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
ns->base.offset = nv30mt->level[level].image_offset[0];
}
+ /* create a linear temporary that we can render into if necessary.
+ * Note that ns->pitch is always a multiple of 64 for linear surfaces and swizzled surfaces are POT, so
+ * ns->pitch & 63 is equivalent to (ns->pitch < 64 && swizzled)*/
+ if((ns->pitch & 63) && (ns->base.usage & (PIPE_BUFFER_USAGE_GPU_WRITE | NOUVEAU_BUFFER_USAGE_NO_RENDER)) == PIPE_BUFFER_USAGE_GPU_WRITE)
+ return &nv04_surface_wrap_for_render(pscreen, ((struct nv30_screen*)pscreen)->eng2d, ns)->base;
+
return &ns->base;
}
static void
nv30_miptree_surface_del(struct pipe_surface *ps)
{
+ struct nv04_surface* ns = (struct nv04_surface*)ps;
+ if(ns->backing)
+ {
+ struct nv30_screen* screen = (struct nv30_screen*)ps->texture->screen;
+ if(ns->backing->base.usage & PIPE_BUFFER_USAGE_GPU_WRITE)
+ screen->eng2d->copy(screen->eng2d, &ns->backing->base, 0, 0, ps, 0, 0, ns->base.width, ns->base.height);
+ nv30_miptree_surface_del(&ns->backing->base);
+ }
+
pipe_texture_reference(&ps->texture, NULL);
FREE(ps);
}
diff --git a/src/gallium/drivers/nv30/nv30_query.c b/src/gallium/drivers/nv30/nv30_query.c
index 1d1c8a484e..e27e9ccbf6 100644
--- a/src/gallium/drivers/nv30/nv30_query.c
+++ b/src/gallium/drivers/nv30/nv30_query.c
@@ -41,6 +41,9 @@ nv30_query_begin(struct pipe_context *pipe, struct pipe_query *pq)
{
struct nv30_context *nv30 = nv30_context(pipe);
struct nv30_query *q = nv30_query(pq);
+ struct nv30_screen *screen = nv30->screen;
+ struct nouveau_channel *chan = screen->base.channel;
+ struct nouveau_grobj *rankine = screen->rankine;
assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER);
@@ -57,10 +60,10 @@ nv30_query_begin(struct pipe_context *pipe, struct pipe_query *pq)
assert(0);
nouveau_notifier_reset(nv30->screen->query, q->object->start);
- BEGIN_RING(rankine, NV34TCL_QUERY_RESET, 1);
- OUT_RING (1);
- BEGIN_RING(rankine, NV34TCL_QUERY_UNK17CC, 1);
- OUT_RING (1);
+ BEGIN_RING(chan, rankine, NV34TCL_QUERY_RESET, 1);
+ OUT_RING (chan, 1);
+ BEGIN_RING(chan, rankine, NV34TCL_QUERY_UNK17CC, 1);
+ OUT_RING (chan, 1);
q->ready = FALSE;
}
@@ -69,12 +72,15 @@ static void
nv30_query_end(struct pipe_context *pipe, struct pipe_query *pq)
{
struct nv30_context *nv30 = nv30_context(pipe);
+ struct nv30_screen *screen = nv30->screen;
+ struct nouveau_channel *chan = screen->base.channel;
+ struct nouveau_grobj *rankine = screen->rankine;
struct nv30_query *q = nv30_query(pq);
- BEGIN_RING(rankine, NV34TCL_QUERY_GET, 1);
- OUT_RING ((0x01 << NV34TCL_QUERY_GET_UNK24_SHIFT) |
+ BEGIN_RING(chan, rankine, NV34TCL_QUERY_GET, 1);
+ OUT_RING (chan, (0x01 << NV34TCL_QUERY_GET_UNK24_SHIFT) |
((q->object->start * 32) << NV34TCL_QUERY_GET_OFFSET_SHIFT));
- FIRE_RING(NULL);
+ FIRE_RING(chan);
}
static boolean
diff --git a/src/gallium/drivers/nv30/nv30_screen.c b/src/gallium/drivers/nv30/nv30_screen.c
index 7cd36902eb..9ed48178dc 100644
--- a/src/gallium/drivers/nv30/nv30_screen.c
+++ b/src/gallium/drivers/nv30/nv30_screen.c
@@ -156,6 +156,12 @@ static void
nv30_screen_destroy(struct pipe_screen *pscreen)
{
struct nv30_screen *screen = nv30_screen(pscreen);
+ unsigned i;
+
+ for (i = 0; i < NV30_STATE_MAX; i++) {
+ if (screen->state[i])
+ so_ref(NULL, &screen->state[i]);
+ }
nouveau_resource_free(&screen->vp_exec_heap);
nouveau_resource_free(&screen->vp_data_heap);
@@ -163,6 +169,9 @@ nv30_screen_destroy(struct pipe_screen *pscreen)
nouveau_notifier_free(&screen->query);
nouveau_notifier_free(&screen->sync);
nouveau_grobj_free(&screen->rankine);
+ nv04_surface_2d_takedown(&screen->eng2d);
+
+ nouveau_screen_fini(&screen->base);
FREE(pscreen);
}
@@ -224,7 +233,6 @@ nv30_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
NOUVEAU_ERR("Error creating 3D object: %d\n", ret);
return FALSE;
}
- BIND_RING(chan, screen->rankine, 7);
/* 2D engine setup */
screen->eng2d = nv04_surface_2d_init(&screen->base);
@@ -261,7 +269,7 @@ nv30_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
}
/* Static rankine initialisation */
- so = so_new(128, 0);
+ so = so_new(36, 60, 0);
so_method(so, screen->rankine, NV34TCL_DMA_NOTIFY, 1);
so_data (so, screen->sync->handle);
so_method(so, screen->rankine, NV34TCL_DMA_TEXTURE0, 2);
diff --git a/src/gallium/drivers/nv30/nv30_state.c b/src/gallium/drivers/nv30/nv30_state.c
index b91e972c12..a80dfb0488 100644
--- a/src/gallium/drivers/nv30/nv30_state.c
+++ b/src/gallium/drivers/nv30/nv30_state.c
@@ -14,7 +14,7 @@ nv30_blend_state_create(struct pipe_context *pipe,
struct nv30_context *nv30 = nv30_context(pipe);
struct nouveau_grobj *rankine = nv30->screen->rankine;
struct nv30_blend_state *bso = CALLOC(1, sizeof(*bso));
- struct nouveau_stateobj *so = so_new(16, 0);
+ struct nouveau_stateobj *so = so_new(5, 8, 0);
if (cso->blend_enable) {
so_method(so, rankine, NV34TCL_BLEND_FUNC_ENABLE, 3);
@@ -300,7 +300,7 @@ nv30_rasterizer_state_create(struct pipe_context *pipe,
{
struct nv30_context *nv30 = nv30_context(pipe);
struct nv30_rasterizer_state *rsso = CALLOC(1, sizeof(*rsso));
- struct nouveau_stateobj *so = so_new(32, 0);
+ struct nouveau_stateobj *so = so_new(9, 19, 0);
struct nouveau_grobj *rankine = nv30->screen->rankine;
/*XXX: ignored:
@@ -435,7 +435,7 @@ nv30_depth_stencil_alpha_state_create(struct pipe_context *pipe,
{
struct nv30_context *nv30 = nv30_context(pipe);
struct nv30_zsa_state *zsaso = CALLOC(1, sizeof(*zsaso));
- struct nouveau_stateobj *so = so_new(32, 0);
+ struct nouveau_stateobj *so = so_new(5, 21, 0);
struct nouveau_grobj *rankine = nv30->screen->rankine;
so_method(so, rankine, NV34TCL_DEPTH_FUNC, 3);
@@ -672,16 +672,6 @@ nv30_set_vertex_elements(struct pipe_context *pipe, unsigned count,
/*nv30->draw_dirty |= NV30_NEW_ARRAYS;*/
}
-static void
-nv30_set_edgeflags(struct pipe_context *pipe, const unsigned *bitfield)
-{
- struct nv30_context *nv30 = nv30_context(pipe);
-
- nv30->edgeflags = bitfield;
- nv30->dirty |= NV30_NEW_ARRAYS;
- /*nv30->draw_dirty |= NV30_NEW_ARRAYS;*/
-}
-
void
nv30_init_state_functions(struct nv30_context *nv30)
{
@@ -690,9 +680,9 @@ nv30_init_state_functions(struct nv30_context *nv30)
nv30->pipe.delete_blend_state = nv30_blend_state_delete;
nv30->pipe.create_sampler_state = nv30_sampler_state_create;
- nv30->pipe.bind_sampler_states = nv30_sampler_state_bind;
+ nv30->pipe.bind_fragment_sampler_states = nv30_sampler_state_bind;
nv30->pipe.delete_sampler_state = nv30_sampler_state_delete;
- nv30->pipe.set_sampler_textures = nv30_set_sampler_texture;
+ nv30->pipe.set_fragment_sampler_textures = nv30_set_sampler_texture;
nv30->pipe.create_rasterizer_state = nv30_rasterizer_state_create;
nv30->pipe.bind_rasterizer_state = nv30_rasterizer_state_bind;
@@ -721,7 +711,6 @@ nv30_init_state_functions(struct nv30_context *nv30)
nv30->pipe.set_scissor_state = nv30_set_scissor_state;
nv30->pipe.set_viewport_state = nv30_set_viewport_state;
- nv30->pipe.set_edgeflags = nv30_set_edgeflags;
nv30->pipe.set_vertex_buffers = nv30_set_vertex_buffers;
nv30->pipe.set_vertex_elements = nv30_set_vertex_elements;
}
diff --git a/src/gallium/drivers/nv30/nv30_state.h b/src/gallium/drivers/nv30/nv30_state.h
index e6f23bf166..e42e872de7 100644
--- a/src/gallium/drivers/nv30/nv30_state.h
+++ b/src/gallium/drivers/nv30/nv30_state.h
@@ -72,6 +72,7 @@ struct nv30_fragment_program {
struct nv30_miptree {
struct pipe_texture base;
+ struct nouveau_bo *bo;
struct pipe_buffer *buffer;
uint total_size;
diff --git a/src/gallium/drivers/nv30/nv30_state_blend.c b/src/gallium/drivers/nv30/nv30_state_blend.c
index 64cf9ae93a..c36d58c040 100644
--- a/src/gallium/drivers/nv30/nv30_state_blend.c
+++ b/src/gallium/drivers/nv30/nv30_state_blend.c
@@ -18,7 +18,7 @@ struct nv30_state_entry nv30_state_blend = {
static boolean
nv30_state_blend_colour_validate(struct nv30_context *nv30)
{
- struct nouveau_stateobj *so = so_new(2, 0);
+ struct nouveau_stateobj *so = so_new(1, 1, 0);
struct pipe_blend_color *bcol = &nv30->blend_colour;
so_method(so, nv30->screen->rankine, NV34TCL_BLEND_COLOR, 1);
diff --git a/src/gallium/drivers/nv30/nv30_state_emit.c b/src/gallium/drivers/nv30/nv30_state_emit.c
index 621b8846c8..ac52d946f0 100644
--- a/src/gallium/drivers/nv30/nv30_state_emit.c
+++ b/src/gallium/drivers/nv30/nv30_state_emit.c
@@ -41,7 +41,7 @@ nv30_state_emit(struct nv30_context *nv30)
struct nouveau_channel *chan = nv30->screen->base.channel;
struct nv30_state *state = &nv30->state;
struct nv30_screen *screen = nv30->screen;
- unsigned i, samplers;
+ unsigned i;
uint64_t states;
if (nv30->pctx_id != screen->cur_pctx) {
@@ -63,6 +63,14 @@ nv30_state_emit(struct nv30_context *nv30)
}
state->dirty = 0;
+}
+
+void
+nv30_state_flush_notify(struct nouveau_channel *chan)
+{
+ struct nv30_context *nv30 = chan->user_private;
+ struct nv30_state *state = &nv30->state;
+ unsigned i, samplers;
so_emit_reloc_markers(chan, state->hw[NV30_STATE_FB]);
for (i = 0, samplers = state->fp_samplers; i < 16 && samplers; i++) {
diff --git a/src/gallium/drivers/nv30/nv30_state_fb.c b/src/gallium/drivers/nv30/nv30_state_fb.c
index 6f6d1740d6..2ed2ea55e8 100644
--- a/src/gallium/drivers/nv30/nv30_state_fb.c
+++ b/src/gallium/drivers/nv30/nv30_state_fb.c
@@ -10,7 +10,7 @@ nv30_state_framebuffer_validate(struct nv30_context *nv30)
struct nv04_surface *rt[2], *zeta = NULL;
uint32_t rt_enable = 0, rt_format = 0;
int i, colour_format = 0, zeta_format = 0, depth_only = 0;
- struct nouveau_stateobj *so = so_new(64, 10);
+ struct nouveau_stateobj *so = so_new(12, 18, 10);
unsigned rt_flags = NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM;
unsigned w = fb->width;
unsigned h = fb->height;
diff --git a/src/gallium/drivers/nv30/nv30_state_scissor.c b/src/gallium/drivers/nv30/nv30_state_scissor.c
index 3ac7a8471e..ba61a9e24a 100644
--- a/src/gallium/drivers/nv30/nv30_state_scissor.c
+++ b/src/gallium/drivers/nv30/nv30_state_scissor.c
@@ -12,7 +12,7 @@ nv30_state_scissor_validate(struct nv30_context *nv30)
return FALSE;
nv30->state.scissor_enabled = rast->scissor;
- so = so_new(3, 0);
+ so = so_new(1, 2, 0);
so_method(so, nv30->screen->rankine, NV34TCL_SCISSOR_HORIZ, 2);
if (nv30->state.scissor_enabled) {
so_data (so, ((s->maxx - s->minx) << 16) | s->minx);
diff --git a/src/gallium/drivers/nv30/nv30_state_stipple.c b/src/gallium/drivers/nv30/nv30_state_stipple.c
index d0c791ac08..ed520a4f43 100644
--- a/src/gallium/drivers/nv30/nv30_state_stipple.c
+++ b/src/gallium/drivers/nv30/nv30_state_stipple.c
@@ -14,14 +14,14 @@ nv30_state_stipple_validate(struct nv30_context *nv30)
if (rast->poly_stipple_enable) {
unsigned i;
- so = so_new(35, 0);
+ so = so_new(2, 33, 0);
so_method(so, rankine, NV34TCL_POLYGON_STIPPLE_ENABLE, 1);
so_data (so, 1);
so_method(so, rankine, NV34TCL_POLYGON_STIPPLE_PATTERN(0), 32);
for (i = 0; i < 32; i++)
so_data(so, nv30->stipple[i]);
} else {
- so = so_new(2, 0);
+ so = so_new(1, 1, 0);
so_method(so, rankine, NV34TCL_POLYGON_STIPPLE_ENABLE, 1);
so_data (so, 0);
}
diff --git a/src/gallium/drivers/nv30/nv30_state_viewport.c b/src/gallium/drivers/nv30/nv30_state_viewport.c
index c3eb413dac..2d7781292b 100644
--- a/src/gallium/drivers/nv30/nv30_state_viewport.c
+++ b/src/gallium/drivers/nv30/nv30_state_viewport.c
@@ -19,7 +19,7 @@ nv30_state_viewport_validate(struct nv30_context *nv30)
return FALSE;
nv30->state.viewport_bypass = bypass;
- so = so_new(11, 0);
+ so = so_new(3, 10, 0);
if (!bypass) {
so_method(so, nv30->screen->rankine,
NV34TCL_VIEWPORT_TRANSLATE_X, 8);
diff --git a/src/gallium/drivers/nv30/nv30_transfer.c b/src/gallium/drivers/nv30/nv30_transfer.c
index 98011decf7..65598991c6 100644
--- a/src/gallium/drivers/nv30/nv30_transfer.c
+++ b/src/gallium/drivers/nv30/nv30_transfer.c
@@ -1,7 +1,9 @@
#include <pipe/p_state.h>
#include <pipe/p_defines.h>
#include <pipe/p_inlines.h>
+#include <util/u_format.h>
#include <util/u_memory.h>
+#include <util/u_math.h>
#include <nouveau/nouveau_winsys.h>
#include "nv30_context.h"
#include "nv30_screen.h"
@@ -10,22 +12,19 @@
struct nv30_transfer {
struct pipe_transfer base;
struct pipe_surface *surface;
- bool direct;
+ boolean direct;
};
static void
-nv30_compatible_transfer_tex(struct pipe_texture *pt, unsigned level,
+nv30_compatible_transfer_tex(struct pipe_texture *pt, unsigned width, unsigned height,
struct pipe_texture *template)
{
memset(template, 0, sizeof(struct pipe_texture));
template->target = pt->target;
template->format = pt->format;
- template->width[0] = pt->width[level];
- template->height[0] = pt->height[level];
- template->depth[0] = 1;
- template->block = pt->block;
- template->nblocksx[0] = pt->nblocksx[level];
- template->nblocksy[0] = pt->nblocksx[level];
+ template->width0 = width;
+ template->height0 = height;
+ template->depth0 = 1;
template->last_level = 0;
template->nr_samples = pt->nr_samples;
@@ -48,14 +47,10 @@ nv30_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
return NULL;
pipe_texture_reference(&tx->base.texture, pt);
- tx->base.format = pt->format;
tx->base.x = x;
tx->base.y = y;
tx->base.width = w;
tx->base.height = h;
- tx->base.block = pt->block;
- tx->base.nblocksx = pt->nblocksx[level];
- tx->base.nblocksy = pt->nblocksy[level];
tx->base.stride = mt->level[level].pitch;
tx->base.usage = usage;
tx->base.face = face;
@@ -76,7 +71,7 @@ nv30_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
tx->direct = false;
- nv30_compatible_transfer_tex(pt, level, &tx_tex_template);
+ nv30_compatible_transfer_tex(pt, w, h, &tx_tex_template);
tx_tex = pscreen->texture_create(pscreen, &tx_tex_template);
if (!tx_tex)
@@ -85,6 +80,8 @@ nv30_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
return NULL;
}
+ tx->base.stride = ((struct nv30_miptree*)tx_tex)->level[0].pitch;
+
tx->surface = pscreen->get_tex_surface(pscreen, tx_tex,
0, 0, 0,
pipe_transfer_buffer_flags(&tx->base));
@@ -110,8 +107,8 @@ nv30_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
/* TODO: Check if SIFM can un-swizzle */
nvscreen->eng2d->copy(nvscreen->eng2d,
tx->surface, 0, 0,
- src, 0, 0,
- src->width, src->height);
+ src, x, y,
+ w, h);
pipe_surface_reference(&src, NULL);
}
@@ -131,13 +128,13 @@ nv30_transfer_del(struct pipe_transfer *ptx)
dst = pscreen->get_tex_surface(pscreen, ptx->texture,
ptx->face, ptx->level, ptx->zslice,
- PIPE_BUFFER_USAGE_GPU_WRITE);
+ PIPE_BUFFER_USAGE_GPU_WRITE | NOUVEAU_BUFFER_USAGE_NO_RENDER);
/* TODO: Check if SIFM can deal with x,y,w,h when swizzling */
nvscreen->eng2d->copy(nvscreen->eng2d,
- dst, 0, 0,
+ dst, tx->base.x, tx->base.y,
tx->surface, 0, 0,
- dst->width, dst->height);
+ tx->base.width, tx->base.height);
pipe_surface_reference(&dst, NULL);
}
@@ -156,8 +153,10 @@ nv30_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx)
void *map = pipe_buffer_map(pscreen, mt->buffer,
pipe_transfer_buffer_flags(ptx));
- return map + ns->base.offset +
- ptx->y * ns->pitch + ptx->x * ptx->block.size;
+ if(!tx->direct)
+ return map + ns->base.offset;
+ else
+ return map + ns->base.offset + ptx->y * ns->pitch + ptx->x * util_format_get_blocksize(ptx->texture->format);
}
static void
diff --git a/src/gallium/drivers/nv30/nv30_vbo.c b/src/gallium/drivers/nv30/nv30_vbo.c
index 189656ec81..1c5db03ea2 100644
--- a/src/gallium/drivers/nv30/nv30_vbo.c
+++ b/src/gallium/drivers/nv30/nv30_vbo.c
@@ -163,19 +163,21 @@ nv30_vbo_static_attrib(struct nv30_context *nv30, struct nouveau_stateobj *so,
return TRUE;
}
-boolean
+void
nv30_draw_arrays(struct pipe_context *pipe,
unsigned mode, unsigned start, unsigned count)
{
struct nv30_context *nv30 = nv30_context(pipe);
- struct nouveau_channel *chan = nv30->screen->base.channel;
+ struct nv30_screen *screen = nv30->screen;
+ struct nouveau_channel *chan = screen->base.channel;
+ struct nouveau_grobj *rankine = screen->rankine;
unsigned restart = 0;
nv30_vbo_set_idxbuf(nv30, NULL, 0);
if (FORCE_SWTNL || !nv30_state_validate(nv30)) {
/*return nv30_draw_elements_swtnl(pipe, NULL, 0,
mode, start, count);*/
- return FALSE;
+ return;
}
while (count) {
@@ -186,17 +188,17 @@ nv30_draw_arrays(struct pipe_context *pipe,
vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 256,
mode, start, count, &restart);
if (!vc) {
- FIRE_RING(NULL);
+ FIRE_RING(chan);
continue;
}
- BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
- OUT_RING (nvgl_primitive(mode));
+ BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+ OUT_RING (chan, nvgl_primitive(mode));
nr = (vc & 0xff);
if (nr) {
- BEGIN_RING(rankine, NV34TCL_VB_VERTEX_BATCH, 1);
- OUT_RING (((nr - 1) << 24) | start);
+ BEGIN_RING(chan, rankine, NV34TCL_VB_VERTEX_BATCH, 1);
+ OUT_RING (chan, ((nr - 1) << 24) | start);
start += nr;
}
@@ -206,15 +208,15 @@ nv30_draw_arrays(struct pipe_context *pipe,
nr -= push;
- BEGIN_RING_NI(rankine, NV34TCL_VB_VERTEX_BATCH, push);
+ BEGIN_RING_NI(chan, rankine, NV34TCL_VB_VERTEX_BATCH, push);
while (push--) {
- OUT_RING(((0x100 - 1) << 24) | start);
+ OUT_RING(chan, ((0x100 - 1) << 24) | start);
start += 0x100;
}
}
- BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
- OUT_RING (0);
+ BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+ OUT_RING (chan, 0);
count -= vc;
start = restart;
@@ -228,7 +230,9 @@ static INLINE void
nv30_draw_elements_u08(struct nv30_context *nv30, void *ib,
unsigned mode, unsigned start, unsigned count)
{
- struct nouveau_channel *chan = nv30->screen->base.channel;
+ struct nv30_screen *screen = nv30->screen;
+ struct nouveau_channel *chan = screen->base.channel;
+ struct nouveau_grobj *rankine = screen->rankine;
while (count) {
uint8_t *elts = (uint8_t *)ib + start;
@@ -239,17 +243,17 @@ nv30_draw_elements_u08(struct nv30_context *nv30, void *ib,
vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 2,
mode, start, count, &restart);
if (vc == 0) {
- FIRE_RING(NULL);
+ FIRE_RING(chan);
continue;
}
count -= vc;
- BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
- OUT_RING (nvgl_primitive(mode));
+ BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+ OUT_RING (chan, nvgl_primitive(mode));
if (vc & 1) {
- BEGIN_RING(rankine, NV34TCL_VB_ELEMENT_U32, 1);
- OUT_RING (elts[0]);
+ BEGIN_RING(chan, rankine, NV34TCL_VB_ELEMENT_U32, 1);
+ OUT_RING (chan, elts[0]);
elts++; vc--;
}
@@ -258,16 +262,16 @@ nv30_draw_elements_u08(struct nv30_context *nv30, void *ib,
push = MIN2(vc, 2047 * 2);
- BEGIN_RING_NI(rankine, NV34TCL_VB_ELEMENT_U16, push >> 1);
+ BEGIN_RING_NI(chan, rankine, NV34TCL_VB_ELEMENT_U16, push >> 1);
for (i = 0; i < push; i+=2)
- OUT_RING((elts[i+1] << 16) | elts[i]);
+ OUT_RING(chan, (elts[i+1] << 16) | elts[i]);
vc -= push;
elts += push;
}
- BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
- OUT_RING (0);
+ BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+ OUT_RING (chan, 0);
start = restart;
}
@@ -277,7 +281,9 @@ static INLINE void
nv30_draw_elements_u16(struct nv30_context *nv30, void *ib,
unsigned mode, unsigned start, unsigned count)
{
- struct nouveau_channel *chan = nv30->screen->base.channel;
+ struct nv30_screen *screen = nv30->screen;
+ struct nouveau_channel *chan = screen->base.channel;
+ struct nouveau_grobj *rankine = screen->rankine;
while (count) {
uint16_t *elts = (uint16_t *)ib + start;
@@ -288,17 +294,17 @@ nv30_draw_elements_u16(struct nv30_context *nv30, void *ib,
vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 2,
mode, start, count, &restart);
if (vc == 0) {
- FIRE_RING(NULL);
+ FIRE_RING(chan);
continue;
}
count -= vc;
- BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
- OUT_RING (nvgl_primitive(mode));
+ BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+ OUT_RING (chan, nvgl_primitive(mode));
if (vc & 1) {
- BEGIN_RING(rankine, NV34TCL_VB_ELEMENT_U32, 1);
- OUT_RING (elts[0]);
+ BEGIN_RING(chan, rankine, NV34TCL_VB_ELEMENT_U32, 1);
+ OUT_RING (chan, elts[0]);
elts++; vc--;
}
@@ -307,16 +313,16 @@ nv30_draw_elements_u16(struct nv30_context *nv30, void *ib,
push = MIN2(vc, 2047 * 2);
- BEGIN_RING_NI(rankine, NV34TCL_VB_ELEMENT_U16, push >> 1);
+ BEGIN_RING_NI(chan, rankine, NV34TCL_VB_ELEMENT_U16, push >> 1);
for (i = 0; i < push; i+=2)
- OUT_RING((elts[i+1] << 16) | elts[i]);
+ OUT_RING(chan, (elts[i+1] << 16) | elts[i]);
vc -= push;
elts += push;
}
- BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
- OUT_RING (0);
+ BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+ OUT_RING (chan, 0);
start = restart;
}
@@ -326,7 +332,9 @@ static INLINE void
nv30_draw_elements_u32(struct nv30_context *nv30, void *ib,
unsigned mode, unsigned start, unsigned count)
{
- struct nouveau_channel *chan = nv30->screen->base.channel;
+ struct nv30_screen *screen = nv30->screen;
+ struct nouveau_channel *chan = screen->base.channel;
+ struct nouveau_grobj *rankine = screen->rankine;
while (count) {
uint32_t *elts = (uint32_t *)ib + start;
@@ -337,32 +345,32 @@ nv30_draw_elements_u32(struct nv30_context *nv30, void *ib,
vc = nouveau_vbuf_split(chan->pushbuf->remaining, 5, 1,
mode, start, count, &restart);
if (vc == 0) {
- FIRE_RING(NULL);
+ FIRE_RING(chan);
continue;
}
count -= vc;
- BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
- OUT_RING (nvgl_primitive(mode));
+ BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+ OUT_RING (chan, nvgl_primitive(mode));
while (vc) {
push = MIN2(vc, 2047);
- BEGIN_RING_NI(rankine, NV34TCL_VB_ELEMENT_U32, push);
- OUT_RINGp (elts, push);
+ BEGIN_RING_NI(chan, rankine, NV34TCL_VB_ELEMENT_U32, push);
+ OUT_RINGp (chan, elts, push);
vc -= push;
elts += push;
}
- BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
- OUT_RING (0);
+ BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+ OUT_RING (chan, 0);
start = restart;
}
}
-static boolean
+static void
nv30_draw_elements_inline(struct pipe_context *pipe,
struct pipe_buffer *ib, unsigned ib_size,
unsigned mode, unsigned start, unsigned count)
@@ -393,15 +401,16 @@ nv30_draw_elements_inline(struct pipe_context *pipe,
}
pipe_buffer_unmap(pscreen, ib);
- return TRUE;
}
-static boolean
+static void
nv30_draw_elements_vbo(struct pipe_context *pipe,
unsigned mode, unsigned start, unsigned count)
{
struct nv30_context *nv30 = nv30_context(pipe);
- struct nouveau_channel *chan = nv30->screen->base.channel;
+ struct nv30_screen *screen = nv30->screen;
+ struct nouveau_channel *chan = screen->base.channel;
+ struct nouveau_grobj *rankine = screen->rankine;
unsigned restart = 0;
while (count) {
@@ -412,17 +421,17 @@ nv30_draw_elements_vbo(struct pipe_context *pipe,
vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 256,
mode, start, count, &restart);
if (!vc) {
- FIRE_RING(NULL);
+ FIRE_RING(chan);
continue;
}
- BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
- OUT_RING (nvgl_primitive(mode));
+ BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+ OUT_RING (chan, nvgl_primitive(mode));
nr = (vc & 0xff);
if (nr) {
- BEGIN_RING(rankine, NV34TCL_VB_INDEX_BATCH, 1);
- OUT_RING (((nr - 1) << 24) | start);
+ BEGIN_RING(chan, rankine, NV34TCL_VB_INDEX_BATCH, 1);
+ OUT_RING (chan, ((nr - 1) << 24) | start);
start += nr;
}
@@ -432,24 +441,22 @@ nv30_draw_elements_vbo(struct pipe_context *pipe,
nr -= push;
- BEGIN_RING_NI(rankine, NV34TCL_VB_INDEX_BATCH, push);
+ BEGIN_RING_NI(chan, rankine, NV34TCL_VB_INDEX_BATCH, push);
while (push--) {
- OUT_RING(((0x100 - 1) << 24) | start);
+ OUT_RING(chan, ((0x100 - 1) << 24) | start);
start += 0x100;
}
}
- BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
- OUT_RING (0);
+ BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+ OUT_RING (chan, 0);
count -= vc;
start = restart;
}
-
- return TRUE;
}
-boolean
+void
nv30_draw_elements(struct pipe_context *pipe,
struct pipe_buffer *indexBuffer, unsigned indexSize,
unsigned mode, unsigned start, unsigned count)
@@ -461,7 +468,7 @@ nv30_draw_elements(struct pipe_context *pipe,
if (FORCE_SWTNL || !nv30_state_validate(nv30)) {
/*return nv30_draw_elements_swtnl(pipe, NULL, 0,
mode, start, count);*/
- return FALSE;
+ return;
}
if (idxbuf) {
@@ -472,7 +479,6 @@ nv30_draw_elements(struct pipe_context *pipe,
}
pipe->flush(pipe, 0, NULL);
- return TRUE;
}
static boolean
@@ -485,14 +491,9 @@ nv30_vbo_validate(struct nv30_context *nv30)
unsigned vb_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
int hw;
- if (nv30->edgeflags) {
- /*nv30->fallback_swtnl |= NV30_NEW_ARRAYS;*/
- return FALSE;
- }
-
- vtxbuf = so_new(20, 18);
+ vtxbuf = so_new(3, 17, 18);
so_method(vtxbuf, rankine, NV34TCL_VTXBUF_ADDRESS(0), nv30->vtxelt_nr);
- vtxfmt = so_new(17, 0);
+ vtxfmt = so_new(1, 16, 0);
so_method(vtxfmt, rankine, NV34TCL_VTXFMT(0), nv30->vtxelt_nr);
for (hw = 0; hw < nv30->vtxelt_nr; hw++) {
@@ -505,7 +506,7 @@ nv30_vbo_validate(struct nv30_context *nv30)
if (!vb->stride) {
if (!sattr)
- sattr = so_new(16 * 5, 0);
+ sattr = so_new(16, 16 * 4, 0);
if (nv30_vbo_static_attrib(nv30, sattr, hw, ve, vb)) {
so_data(vtxbuf, 0);
diff --git a/src/gallium/drivers/nv30/nv30_vertprog.c b/src/gallium/drivers/nv30/nv30_vertprog.c
index 14a5c0260d..e77a5be3f2 100644
--- a/src/gallium/drivers/nv30/nv30_vertprog.c
+++ b/src/gallium/drivers/nv30/nv30_vertprog.c
@@ -253,32 +253,32 @@ static INLINE struct nv30_sreg
tgsi_src(struct nv30_vpc *vpc, const struct tgsi_full_src_register *fsrc) {
struct nv30_sreg src;
- switch (fsrc->SrcRegister.File) {
+ switch (fsrc->Register.File) {
case TGSI_FILE_INPUT:
- src = nv30_sr(NV30SR_INPUT, fsrc->SrcRegister.Index);
+ src = nv30_sr(NV30SR_INPUT, fsrc->Register.Index);
break;
case TGSI_FILE_CONSTANT:
- src = constant(vpc, fsrc->SrcRegister.Index, 0, 0, 0, 0);
+ src = constant(vpc, fsrc->Register.Index, 0, 0, 0, 0);
break;
case TGSI_FILE_IMMEDIATE:
- src = vpc->imm[fsrc->SrcRegister.Index];
+ src = vpc->imm[fsrc->Register.Index];
break;
case TGSI_FILE_TEMPORARY:
- if (vpc->high_temp < fsrc->SrcRegister.Index)
- vpc->high_temp = fsrc->SrcRegister.Index;
- src = nv30_sr(NV30SR_TEMP, fsrc->SrcRegister.Index);
+ if (vpc->high_temp < fsrc->Register.Index)
+ vpc->high_temp = fsrc->Register.Index;
+ src = nv30_sr(NV30SR_TEMP, fsrc->Register.Index);
break;
default:
NOUVEAU_ERR("bad src file\n");
break;
}
- src.abs = fsrc->SrcRegisterExtMod.Absolute;
- src.negate = fsrc->SrcRegister.Negate;
- src.swz[0] = fsrc->SrcRegister.SwizzleX;
- src.swz[1] = fsrc->SrcRegister.SwizzleY;
- src.swz[2] = fsrc->SrcRegister.SwizzleZ;
- src.swz[3] = fsrc->SrcRegister.SwizzleW;
+ src.abs = fsrc->Register.Absolute;
+ src.negate = fsrc->Register.Negate;
+ src.swz[0] = fsrc->Register.SwizzleX;
+ src.swz[1] = fsrc->Register.SwizzleY;
+ src.swz[2] = fsrc->Register.SwizzleZ;
+ src.swz[3] = fsrc->Register.SwizzleW;
return src;
}
@@ -286,14 +286,14 @@ static INLINE struct nv30_sreg
tgsi_dst(struct nv30_vpc *vpc, const struct tgsi_full_dst_register *fdst) {
struct nv30_sreg dst;
- switch (fdst->DstRegister.File) {
+ switch (fdst->Register.File) {
case TGSI_FILE_OUTPUT:
dst = nv30_sr(NV30SR_OUTPUT,
- vpc->output_map[fdst->DstRegister.Index]);
+ vpc->output_map[fdst->Register.Index]);
break;
case TGSI_FILE_TEMPORARY:
- dst = nv30_sr(NV30SR_TEMP, fdst->DstRegister.Index);
+ dst = nv30_sr(NV30SR_TEMP, fdst->Register.Index);
if (vpc->high_temp < dst.index)
vpc->high_temp = dst.index;
break;
@@ -334,8 +334,8 @@ nv30_vertprog_parse_instruction(struct nv30_vpc *vpc,
for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
const struct tgsi_full_src_register *fsrc;
- fsrc = &finst->FullSrcRegisters[i];
- if (fsrc->SrcRegister.File == TGSI_FILE_TEMPORARY) {
+ fsrc = &finst->Src[i];
+ if (fsrc->Register.File == TGSI_FILE_TEMPORARY) {
src[i] = tgsi_src(vpc, fsrc);
}
}
@@ -343,11 +343,11 @@ nv30_vertprog_parse_instruction(struct nv30_vpc *vpc,
for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
const struct tgsi_full_src_register *fsrc;
- fsrc = &finst->FullSrcRegisters[i];
- switch (fsrc->SrcRegister.File) {
+ fsrc = &finst->Src[i];
+ switch (fsrc->Register.File) {
case TGSI_FILE_INPUT:
- if (ai == -1 || ai == fsrc->SrcRegister.Index) {
- ai = fsrc->SrcRegister.Index;
+ if (ai == -1 || ai == fsrc->Register.Index) {
+ ai = fsrc->Register.Index;
src[i] = tgsi_src(vpc, fsrc);
} else {
src[i] = temp(vpc);
@@ -360,8 +360,8 @@ nv30_vertprog_parse_instruction(struct nv30_vpc *vpc,
*/
case TGSI_FILE_CONSTANT:
case TGSI_FILE_IMMEDIATE:
- if (ci == -1 || ci == fsrc->SrcRegister.Index) {
- ci = fsrc->SrcRegister.Index;
+ if (ci == -1 || ci == fsrc->Register.Index) {
+ ci = fsrc->Register.Index;
src[i] = tgsi_src(vpc, fsrc);
} else {
src[i] = temp(vpc);
@@ -378,8 +378,8 @@ nv30_vertprog_parse_instruction(struct nv30_vpc *vpc,
}
}
- dst = tgsi_dst(vpc, &finst->FullDstRegisters[0]);
- mask = tgsi_mask(finst->FullDstRegisters[0].DstRegister.WriteMask);
+ dst = tgsi_dst(vpc, &finst->Dst[0]);
+ mask = tgsi_mask(finst->Dst[0].Register.WriteMask);
switch (finst->Instruction.Opcode) {
case TGSI_OPCODE_ABS:
@@ -490,15 +490,15 @@ nv30_vertprog_parse_decl_output(struct nv30_vpc *vpc,
{
int hw;
- switch (fdec->Semantic.SemanticName) {
+ switch (fdec->Semantic.Name) {
case TGSI_SEMANTIC_POSITION:
hw = NV30_VP_INST_DEST_POS;
break;
case TGSI_SEMANTIC_COLOR:
- if (fdec->Semantic.SemanticIndex == 0) {
+ if (fdec->Semantic.Index == 0) {
hw = NV30_VP_INST_DEST_COL0;
} else
- if (fdec->Semantic.SemanticIndex == 1) {
+ if (fdec->Semantic.Index == 1) {
hw = NV30_VP_INST_DEST_COL1;
} else {
NOUVEAU_ERR("bad colour semantic index\n");
@@ -506,10 +506,10 @@ nv30_vertprog_parse_decl_output(struct nv30_vpc *vpc,
}
break;
case TGSI_SEMANTIC_BCOLOR:
- if (fdec->Semantic.SemanticIndex == 0) {
+ if (fdec->Semantic.Index == 0) {
hw = NV30_VP_INST_DEST_BFC0;
} else
- if (fdec->Semantic.SemanticIndex == 1) {
+ if (fdec->Semantic.Index == 1) {
hw = NV30_VP_INST_DEST_BFC1;
} else {
NOUVEAU_ERR("bad bcolour semantic index\n");
@@ -523,19 +523,22 @@ nv30_vertprog_parse_decl_output(struct nv30_vpc *vpc,
hw = NV30_VP_INST_DEST_PSZ;
break;
case TGSI_SEMANTIC_GENERIC:
- if (fdec->Semantic.SemanticIndex <= 7) {
- hw = NV30_VP_INST_DEST_TC(fdec->Semantic.SemanticIndex);
+ if (fdec->Semantic.Index <= 7) {
+ hw = NV30_VP_INST_DEST_TC(fdec->Semantic.Index);
} else {
NOUVEAU_ERR("bad generic semantic index\n");
return FALSE;
}
break;
+ case TGSI_SEMANTIC_EDGEFLAG:
+ NOUVEAU_ERR("cannot handle edgeflag output\n");
+ return FALSE;
default:
NOUVEAU_ERR("bad output semantic\n");
return FALSE;
}
- vpc->output_map[fdec->DeclarationRange.First] = hw;
+ vpc->output_map[fdec->Range.First] = hw;
return TRUE;
}
@@ -647,7 +650,9 @@ static boolean
nv30_vertprog_validate(struct nv30_context *nv30)
{
struct pipe_screen *pscreen = nv30->pipe.screen;
- struct nouveau_grobj *rankine = nv30->screen->rankine;
+ struct nv30_screen *screen = nv30->screen;
+ struct nouveau_channel *chan = screen->base.channel;
+ struct nouveau_grobj *rankine = screen->rankine;
struct nv30_vertex_program *vp;
struct pipe_buffer *constbuf;
boolean upload_code = FALSE, upload_data = FALSE;
@@ -681,7 +686,7 @@ nv30_vertprog_validate(struct nv30_context *nv30)
assert(0);
}
- so = so_new(2, 0);
+ so = so_new(1, 1, 0);
so_method(so, rankine, NV34TCL_VP_START_FROM_ID, 1);
so_data (so, vp->exec->start);
so_ref(so, &vp->so);
@@ -767,9 +772,9 @@ nv30_vertprog_validate(struct nv30_context *nv30)
4 * sizeof(float));
}
- BEGIN_RING(rankine, NV34TCL_VP_UPLOAD_CONST_ID, 5);
- OUT_RING (i + vp->data->start);
- OUT_RINGp ((uint32_t *)vpd->value, 4);
+ BEGIN_RING(chan, rankine, NV34TCL_VP_UPLOAD_CONST_ID, 5);
+ OUT_RING (chan, i + vp->data->start);
+ OUT_RINGp (chan, (uint32_t *)vpd->value, 4);
}
if (constbuf)
@@ -785,11 +790,11 @@ nv30_vertprog_validate(struct nv30_context *nv30)
vp->insns[i].data[2], vp->insns[i].data[3]);
}
#endif
- BEGIN_RING(rankine, NV34TCL_VP_UPLOAD_FROM_ID, 1);
- OUT_RING (vp->exec->start);
+ BEGIN_RING(chan, rankine, NV34TCL_VP_UPLOAD_FROM_ID, 1);
+ OUT_RING (chan, vp->exec->start);
for (i = 0; i < vp->nr_insns; i++) {
- BEGIN_RING(rankine, NV34TCL_VP_UPLOAD_INST(0), 4);
- OUT_RINGp (vp->insns[i].data, 4);
+ BEGIN_RING(chan, rankine, NV34TCL_VP_UPLOAD_INST(0), 4);
+ OUT_RINGp (chan, vp->insns[i].data, 4);
}
}