diff options
author | Luca Barbieri <[email protected]> | 2010-02-21 00:59:30 +0100 |
---|---|---|
committer | Younes Manton <[email protected]> | 2010-03-15 00:03:02 -0400 |
commit | cd0d03adab65a9586e0c5d60e9ee487677914f3b (patch) | |
tree | 0cd09ba062fd9389886ad23ea566571be66bcec3 /src | |
parent | 4d93ef1a015c8ec7341b0793e87ec375014436b3 (diff) |
nv30, nv40: non-trivially unify nv[34]0_state_fb.c
The files are significantly different due to:
1. nv30 support 2 render targets, nv40 4
2. z-buffer pitch is set differently
3. nv30 has a limitation of colour_bits >= zeta_bits. This may not
actually exist in the driver though
4. nv30 points color0 at depth in the depth-only case
5. nv30 sets NV34TCL_VIEWPORT_TX_ORIGIN to 0. This is probably
unnecessary
This patch attempts to unify the two files and preserve the existing
behavior.
Diffstat (limited to 'src')
-rw-r--r-- | src/gallium/drivers/nv30/Makefile | 1 | ||||
-rw-r--r-- | src/gallium/drivers/nv30/nv30_context.h | 1 | ||||
-rw-r--r-- | src/gallium/drivers/nv40/Makefile | 1 | ||||
-rw-r--r-- | src/gallium/drivers/nv40/nv40_context.h | 1 | ||||
-rw-r--r-- | src/gallium/drivers/nv40/nv40_state_fb.c | 175 | ||||
-rw-r--r-- | src/gallium/drivers/nvfx/Makefile | 1 | ||||
-rw-r--r-- | src/gallium/drivers/nvfx/nvfx_context.h | 1 | ||||
-rw-r--r-- | src/gallium/drivers/nvfx/nvfx_state_emit.c | 2 | ||||
-rw-r--r-- | src/gallium/drivers/nvfx/nvfx_state_fb.c (renamed from src/gallium/drivers/nv30/nv30_state_fb.c) | 125 |
9 files changed, 96 insertions, 212 deletions
diff --git a/src/gallium/drivers/nv30/Makefile b/src/gallium/drivers/nv30/Makefile index 6ee0d8f248a..b5728a34f83 100644 --- a/src/gallium/drivers/nv30/Makefile +++ b/src/gallium/drivers/nv30/Makefile @@ -10,7 +10,6 @@ C_SOURCES = \ nv30_fragtex.c \ nv30_screen.c \ nv30_state.c \ - nv30_state_fb.c \ nv30_vbo.c \ nv30_vertprog.c diff --git a/src/gallium/drivers/nv30/nv30_context.h b/src/gallium/drivers/nv30/nv30_context.h index 37def47b61d..c203425cc91 100644 --- a/src/gallium/drivers/nv30/nv30_context.h +++ b/src/gallium/drivers/nv30/nv30_context.h @@ -22,7 +22,6 @@ extern void nv30_fragtex_bind(struct nvfx_context *); /* nv30_state.c and friends */ extern struct nvfx_state_entry nv30_state_fragprog; extern struct nvfx_state_entry nv30_state_vertprog; -extern struct nvfx_state_entry nv30_state_framebuffer; extern struct nvfx_state_entry nv30_state_fragtex; extern struct nvfx_state_entry nv30_state_vbo; diff --git a/src/gallium/drivers/nv40/Makefile b/src/gallium/drivers/nv40/Makefile index 85d6ce98861..f78e81ac4b3 100644 --- a/src/gallium/drivers/nv40/Makefile +++ b/src/gallium/drivers/nv40/Makefile @@ -10,7 +10,6 @@ C_SOURCES = \ nv40_fragtex.c \ nv40_screen.c \ nv40_state.c \ - nv40_state_fb.c \ nv40_vbo.c \ nv40_vertprog.c diff --git a/src/gallium/drivers/nv40/nv40_context.h b/src/gallium/drivers/nv40/nv40_context.h index a3000eeca04..3840134ce69 100644 --- a/src/gallium/drivers/nv40/nv40_context.h +++ b/src/gallium/drivers/nv40/nv40_context.h @@ -26,7 +26,6 @@ extern void nv40_fragtex_bind(struct nvfx_context *); /* nv40_state.c and friends */ extern struct nvfx_state_entry nv40_state_fragprog; extern struct nvfx_state_entry nv40_state_vertprog; -extern struct nvfx_state_entry nv40_state_framebuffer; extern struct nvfx_state_entry nv40_state_fragtex; extern struct nvfx_state_entry nv40_state_vbo; extern struct nvfx_state_entry nv40_state_vtxfmt; diff --git a/src/gallium/drivers/nv40/nv40_state_fb.c b/src/gallium/drivers/nv40/nv40_state_fb.c deleted file mode 100644 index 95735e40a38..00000000000 --- a/src/gallium/drivers/nv40/nv40_state_fb.c +++ /dev/null @@ -1,175 +0,0 @@ -#include "nv40_context.h" -#include "nouveau/nouveau_util.h" - -static struct pipe_buffer * -nv40_do_surface_buffer(struct pipe_surface *surface) -{ - struct nvfx_miptree *mt = (struct nvfx_miptree *)surface->texture; - return mt->buffer; -} - -#define nv40_surface_buffer(ps) nouveau_bo(nv40_do_surface_buffer(ps)) - -static boolean -nv40_state_framebuffer_validate(struct nvfx_context *nvfx) -{ - struct nouveau_channel *chan = nvfx->screen->base.channel; - struct nouveau_grobj *eng3d = nvfx->screen->eng3d; - struct pipe_framebuffer_state *fb = &nvfx->framebuffer; - struct nv04_surface *rt[4], *zeta; - uint32_t rt_enable, rt_format; - int i, colour_format = 0, zeta_format = 0; - struct nouveau_stateobj *so = so_new(18, 24, 10); - unsigned rt_flags = NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM; - unsigned w = fb->width; - unsigned h = fb->height; - - rt_enable = 0; - for (i = 0; i < fb->nr_cbufs; i++) { - if (colour_format) { - assert(colour_format == fb->cbufs[i]->format); - } else { - colour_format = fb->cbufs[i]->format; - rt_enable |= (NV40TCL_RT_ENABLE_COLOR0 << i); - rt[i] = (struct nv04_surface *)fb->cbufs[i]; - } - } - - if (rt_enable & (NV40TCL_RT_ENABLE_COLOR1 | NV40TCL_RT_ENABLE_COLOR2 | - NV40TCL_RT_ENABLE_COLOR3)) - rt_enable |= NV40TCL_RT_ENABLE_MRT; - - if (fb->zsbuf) { - zeta_format = fb->zsbuf->format; - zeta = (struct nv04_surface *)fb->zsbuf; - } - - if (!(rt[0]->base.texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) { - assert(!(fb->width & (fb->width - 1)) && !(fb->height & (fb->height - 1))); - for (i = 1; i < fb->nr_cbufs; i++) - assert(!(rt[i]->base.texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)); - - rt_format = NV34TCL_RT_FORMAT_TYPE_SWIZZLED | - log2i(fb->width) << NV34TCL_RT_FORMAT_LOG2_WIDTH_SHIFT | - log2i(fb->height) << NV34TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT; - } - else - rt_format = NV34TCL_RT_FORMAT_TYPE_LINEAR; - - switch (colour_format) { - case PIPE_FORMAT_B8G8R8X8_UNORM: - rt_format |= NV34TCL_RT_FORMAT_COLOR_X8R8G8B8; - break; - case PIPE_FORMAT_B8G8R8A8_UNORM: - case 0: - rt_format |= NV34TCL_RT_FORMAT_COLOR_A8R8G8B8; - break; - case PIPE_FORMAT_B5G6R5_UNORM: - rt_format |= NV34TCL_RT_FORMAT_COLOR_R5G6B5; - break; - default: - assert(0); - } - - switch (zeta_format) { - case PIPE_FORMAT_Z16_UNORM: - rt_format |= NV34TCL_RT_FORMAT_ZETA_Z16; - break; - case PIPE_FORMAT_S8Z24_UNORM: - case PIPE_FORMAT_X8Z24_UNORM: - case 0: - rt_format |= NV34TCL_RT_FORMAT_ZETA_Z24S8; - break; - default: - assert(0); - } - - if (rt_enable & NV40TCL_RT_ENABLE_COLOR0) { - so_method(so, eng3d, NV34TCL_DMA_COLOR0, 1); - so_reloc (so, nv40_surface_buffer(&rt[0]->base), 0, - rt_flags | NOUVEAU_BO_OR, - chan->vram->handle, chan->gart->handle); - so_method(so, eng3d, NV34TCL_COLOR0_PITCH, 2); - so_data (so, rt[0]->pitch); - so_reloc (so, nv40_surface_buffer(&rt[0]->base), - rt[0]->base.offset, rt_flags | NOUVEAU_BO_LOW, - 0, 0); - } - - if (rt_enable & NV40TCL_RT_ENABLE_COLOR1) { - so_method(so, eng3d, NV34TCL_DMA_COLOR1, 1); - so_reloc (so, nv40_surface_buffer(&rt[1]->base), 0, - rt_flags | NOUVEAU_BO_OR, - chan->vram->handle, chan->gart->handle); - so_method(so, eng3d, NV34TCL_COLOR1_OFFSET, 2); - so_reloc (so, nv40_surface_buffer(&rt[1]->base), - rt[1]->base.offset, rt_flags | NOUVEAU_BO_LOW, - 0, 0); - so_data (so, rt[1]->pitch); - } - - if (rt_enable & NV40TCL_RT_ENABLE_COLOR2) { - so_method(so, eng3d, NV40TCL_DMA_COLOR2, 1); - so_reloc (so, nv40_surface_buffer(&rt[2]->base), 0, - rt_flags | NOUVEAU_BO_OR, - chan->vram->handle, chan->gart->handle); - so_method(so, eng3d, NV40TCL_COLOR2_OFFSET, 1); - so_reloc (so, nv40_surface_buffer(&rt[2]->base), - rt[2]->base.offset, rt_flags | NOUVEAU_BO_LOW, - 0, 0); - so_method(so, eng3d, NV40TCL_COLOR2_PITCH, 1); - so_data (so, rt[2]->pitch); - } - - if (rt_enable & NV40TCL_RT_ENABLE_COLOR3) { - so_method(so, eng3d, NV40TCL_DMA_COLOR3, 1); - so_reloc (so, nv40_surface_buffer(&rt[3]->base), 0, - rt_flags | NOUVEAU_BO_OR, - chan->vram->handle, chan->gart->handle); - so_method(so, eng3d, NV40TCL_COLOR3_OFFSET, 1); - so_reloc (so, nv40_surface_buffer(&rt[3]->base), - rt[3]->base.offset, rt_flags | NOUVEAU_BO_LOW, - 0, 0); - so_method(so, eng3d, NV40TCL_COLOR3_PITCH, 1); - so_data (so, rt[3]->pitch); - } - - if (zeta_format) { - so_method(so, eng3d, NV34TCL_DMA_ZETA, 1); - so_reloc (so, nv40_surface_buffer(&zeta->base), 0, - rt_flags | NOUVEAU_BO_OR, - chan->vram->handle, chan->gart->handle); - so_method(so, eng3d, NV34TCL_ZETA_OFFSET, 1); - so_reloc (so, nv40_surface_buffer(&zeta->base), - zeta->base.offset, rt_flags | NOUVEAU_BO_LOW, 0, 0); - so_method(so, eng3d, NV40TCL_ZETA_PITCH, 1); - so_data (so, zeta->pitch); - } - - so_method(so, eng3d, NV40TCL_RT_ENABLE, 1); - so_data (so, rt_enable); - so_method(so, eng3d, NV34TCL_RT_HORIZ, 3); - so_data (so, (w << 16) | 0); - so_data (so, (h << 16) | 0); - so_data (so, rt_format); - so_method(so, eng3d, NV34TCL_VIEWPORT_HORIZ, 2); - so_data (so, (w << 16) | 0); - so_data (so, (h << 16) | 0); - so_method(so, eng3d, NV34TCL_VIEWPORT_CLIP_HORIZ(0), 2); - so_data (so, ((w - 1) << 16) | 0); - so_data (so, ((h - 1) << 16) | 0); - so_method(so, eng3d, 0x1d88, 1); - so_data (so, (1 << 12) | h); - - so_ref(so, &nvfx->state.hw[NVFX_STATE_FB]); - so_ref(NULL, &so); - return TRUE; -} - -struct nvfx_state_entry nv40_state_framebuffer = { - .validate = nv40_state_framebuffer_validate, - .dirty = { - .pipe = NVFX_NEW_FB, - .hw = NVFX_STATE_FB - } -}; diff --git a/src/gallium/drivers/nvfx/Makefile b/src/gallium/drivers/nvfx/Makefile index 2f198d9d1a2..2f80681e5cf 100644 --- a/src/gallium/drivers/nvfx/Makefile +++ b/src/gallium/drivers/nvfx/Makefile @@ -9,6 +9,7 @@ C_SOURCES = \ nvfx_miptree.c \ nvfx_query.c \ nvfx_state_blend.c \ + nvfx_state_fb.c \ nvfx_state_rasterizer.c \ nvfx_state_scissor.c \ nvfx_state_stipple.c \ diff --git a/src/gallium/drivers/nvfx/nvfx_context.h b/src/gallium/drivers/nvfx/nvfx_context.h index b6e6cf8fd95..28daa1d2e7a 100644 --- a/src/gallium/drivers/nvfx/nvfx_context.h +++ b/src/gallium/drivers/nvfx/nvfx_context.h @@ -183,6 +183,7 @@ struct nvfx_state_entry { extern struct nvfx_state_entry nvfx_state_blend; extern struct nvfx_state_entry nvfx_state_blend_colour; +extern struct nvfx_state_entry nvfx_state_framebuffer; extern struct nvfx_state_entry nvfx_state_rasterizer; extern struct nvfx_state_entry nvfx_state_scissor; extern struct nvfx_state_entry nvfx_state_sr; diff --git a/src/gallium/drivers/nvfx/nvfx_state_emit.c b/src/gallium/drivers/nvfx/nvfx_state_emit.c index b86cb44936a..d3088e42112 100644 --- a/src/gallium/drivers/nvfx/nvfx_state_emit.c +++ b/src/gallium/drivers/nvfx/nvfx_state_emit.c @@ -5,7 +5,7 @@ #define RENDER_STATES(name, nvxx, vbo) \ static struct nvfx_state_entry *name##_render_states[] = { \ - &nvxx##_state_framebuffer, \ + &nvfx_state_framebuffer, \ &nvfx_state_rasterizer, \ &nvfx_state_scissor, \ &nvfx_state_stipple, \ diff --git a/src/gallium/drivers/nv30/nv30_state_fb.c b/src/gallium/drivers/nvfx/nvfx_state_fb.c index e9e215dccea..dd64ba4193c 100644 --- a/src/gallium/drivers/nv30/nv30_state_fb.c +++ b/src/gallium/drivers/nvfx/nvfx_state_fb.c @@ -1,22 +1,36 @@ -#include "nv30_context.h" +#include "nvfx_context.h" #include "nouveau/nouveau_util.h" +static struct pipe_buffer * +nvfx_do_surface_buffer(struct pipe_surface *surface) +{ + struct nvfx_miptree *mt = (struct nvfx_miptree *)surface->texture; + return mt->buffer; +} + +#define nvfx_surface_buffer(ps) nouveau_bo(nvfx_do_surface_buffer(ps)) + static boolean -nv30_state_framebuffer_validate(struct nvfx_context *nvfx) +nvfx_state_framebuffer_validate(struct nvfx_context *nvfx) { struct pipe_framebuffer_state *fb = &nvfx->framebuffer; struct nouveau_channel *chan = nvfx->screen->base.channel; struct nouveau_grobj *eng3d = nvfx->screen->eng3d; - struct nv04_surface *rt[2], *zeta = NULL; + struct nv04_surface *rt[4], *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(12, 18, 10); + int i, colour_format = 0, zeta_format = 0; + int depth_only = 0; + struct nouveau_stateobj *so = so_new(18, 24, 10); unsigned rt_flags = NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM; unsigned w = fb->width; unsigned h = fb->height; - struct nvfx_miptree *nv30mt; int colour_bits = 32, zeta_bits = 32; + if(!nvfx->is_nv4x) + assert(fb->nr_cbufs <= 2); + else + assert(fb->nr_cbufs <= 4); + for (i = 0; i < fb->nr_cbufs; i++) { if (colour_format) { assert(colour_format == fb->cbufs[i]->format); @@ -27,7 +41,8 @@ nv30_state_framebuffer_validate(struct nvfx_context *nvfx) } } - if (rt_enable & NV34TCL_RT_ENABLE_COLOR1) + if (rt_enable & (NV34TCL_RT_ENABLE_COLOR1 | + NV40TCL_RT_ENABLE_COLOR2 | NV40TCL_RT_ENABLE_COLOR3)) rt_enable |= NV34TCL_RT_ENABLE_MRT; if (fb->zsbuf) { @@ -35,7 +50,8 @@ nv30_state_framebuffer_validate(struct nvfx_context *nvfx) zeta = (struct nv04_surface *)fb->zsbuf; } - if (rt_enable & (NV34TCL_RT_ENABLE_COLOR0|NV34TCL_RT_ENABLE_COLOR1)) { + if (rt_enable & (NV34TCL_RT_ENABLE_COLOR0 | NV34TCL_RT_ENABLE_COLOR1 | + NV40TCL_RT_ENABLE_COLOR2 | NV40TCL_RT_ENABLE_COLOR3)) { /* Render to at least a colour buffer */ if (!(rt[0]->base.texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) { assert(!(fb->width & (fb->width - 1)) && !(fb->height & (fb->height - 1))); @@ -95,50 +111,91 @@ nv30_state_framebuffer_validate(struct nvfx_context *nvfx) assert(0); } - if (colour_bits > zeta_bits) { + if ((!nvfx->is_nv4x) && colour_bits > zeta_bits) { + /* TODO: does this limitation really exist? + TODO: can it be worked around somehow? */ return FALSE; } - if (depth_only || (rt_enable & NV34TCL_RT_ENABLE_COLOR0)) { + if ((rt_enable & NV34TCL_RT_ENABLE_COLOR0) + || ((!nvfx->is_nv4x) && depth_only)) { struct nv04_surface *rt0 = (depth_only ? zeta : rt[0]); uint32_t pitch = rt0->pitch; - if (zeta) { - pitch |= (zeta->pitch << 16); - } else { - pitch |= (pitch << 16); + if(!nvfx->is_nv4x) + { + if (zeta) { + pitch |= (zeta->pitch << 16); + } else { + pitch |= (pitch << 16); + } } - nv30mt = (struct nvfx_miptree *) rt0->base.texture; so_method(so, eng3d, NV34TCL_DMA_COLOR0, 1); - so_reloc (so, nouveau_bo(nv30mt->buffer), 0, rt_flags | NOUVEAU_BO_OR, + so_reloc (so, nvfx_surface_buffer(&rt0->base), 0, + rt_flags | NOUVEAU_BO_OR, chan->vram->handle, chan->gart->handle); so_method(so, eng3d, NV34TCL_COLOR0_PITCH, 2); so_data (so, pitch); - so_reloc (so, nouveau_bo(nv30mt->buffer), rt0->base.offset, - rt_flags | NOUVEAU_BO_LOW, 0, 0); + so_reloc (so, nvfx_surface_buffer(&rt[0]->base), + rt0->base.offset, rt_flags | NOUVEAU_BO_LOW, + 0, 0); } if (rt_enable & NV34TCL_RT_ENABLE_COLOR1) { - nv30mt = (struct nvfx_miptree *)rt[1]->base.texture; so_method(so, eng3d, NV34TCL_DMA_COLOR1, 1); - so_reloc (so, nouveau_bo(nv30mt->buffer), 0, rt_flags | NOUVEAU_BO_OR, + so_reloc (so, nvfx_surface_buffer(&rt[1]->base), 0, + rt_flags | NOUVEAU_BO_OR, chan->vram->handle, chan->gart->handle); so_method(so, eng3d, NV34TCL_COLOR1_OFFSET, 2); - so_reloc (so, nouveau_bo(nv30mt->buffer), rt[1]->base.offset, - rt_flags | NOUVEAU_BO_LOW, 0, 0); + so_reloc (so, nvfx_surface_buffer(&rt[1]->base), + rt[1]->base.offset, rt_flags | NOUVEAU_BO_LOW, + 0, 0); so_data (so, rt[1]->pitch); } + if(nvfx->is_nv4x) + { + if (rt_enable & NV40TCL_RT_ENABLE_COLOR2) { + so_method(so, eng3d, NV40TCL_DMA_COLOR2, 1); + so_reloc (so, nvfx_surface_buffer(&rt[2]->base), 0, + rt_flags | NOUVEAU_BO_OR, + chan->vram->handle, chan->gart->handle); + so_method(so, eng3d, NV40TCL_COLOR2_OFFSET, 1); + so_reloc (so, nvfx_surface_buffer(&rt[2]->base), + rt[2]->base.offset, rt_flags | NOUVEAU_BO_LOW, + 0, 0); + so_method(so, eng3d, NV40TCL_COLOR2_PITCH, 1); + so_data (so, rt[2]->pitch); + } + + if (rt_enable & NV40TCL_RT_ENABLE_COLOR3) { + so_method(so, eng3d, NV40TCL_DMA_COLOR3, 1); + so_reloc (so, nvfx_surface_buffer(&rt[3]->base), 0, + rt_flags | NOUVEAU_BO_OR, + chan->vram->handle, chan->gart->handle); + so_method(so, eng3d, NV40TCL_COLOR3_OFFSET, 1); + so_reloc (so, nvfx_surface_buffer(&rt[3]->base), + rt[3]->base.offset, rt_flags | NOUVEAU_BO_LOW, + 0, 0); + so_method(so, eng3d, NV40TCL_COLOR3_PITCH, 1); + so_data (so, rt[3]->pitch); + } + } + if (zeta_format) { - nv30mt = (struct nvfx_miptree *)zeta->base.texture; so_method(so, eng3d, NV34TCL_DMA_ZETA, 1); - so_reloc (so, nouveau_bo(nv30mt->buffer), 0, rt_flags | NOUVEAU_BO_OR, + so_reloc (so, nvfx_surface_buffer(&zeta->base), 0, + rt_flags | NOUVEAU_BO_OR, chan->vram->handle, chan->gart->handle); so_method(so, eng3d, NV34TCL_ZETA_OFFSET, 1); - so_reloc (so, nouveau_bo(nv30mt->buffer), zeta->base.offset, - rt_flags | NOUVEAU_BO_LOW, 0, 0); - /* TODO: allocate LMA depth buffer */ + /* TODO: reverse engineer LMA */ + so_reloc (so, nvfx_surface_buffer(&zeta->base), + zeta->base.offset, rt_flags | NOUVEAU_BO_LOW, 0, 0); + if(nvfx->is_nv4x) { + so_method(so, eng3d, NV40TCL_ZETA_PITCH, 1); + so_data (so, zeta->pitch); + } } so_method(so, eng3d, NV34TCL_RT_ENABLE, 1); @@ -155,17 +212,21 @@ nv30_state_framebuffer_validate(struct nvfx_context *nvfx) so_data (so, ((h - 1) << 16) | 0); so_method(so, eng3d, 0x1d88, 1); so_data (so, (1 << 12) | h); - /* Wonder why this is needed, context should all be set to zero on init */ - so_method(so, eng3d, NV34TCL_VIEWPORT_TX_ORIGIN, 1); - so_data (so, 0); + + if(!nvfx->is_nv4x) { + /* Wonder why this is needed, context should all be set to zero on init */ + /* TODO: we can most likely remove this, after putting it in context init */ + so_method(so, eng3d, NV34TCL_VIEWPORT_TX_ORIGIN, 1); + so_data (so, 0); + } so_ref(so, &nvfx->state.hw[NVFX_STATE_FB]); so_ref(NULL, &so); return TRUE; } -struct nvfx_state_entry nv30_state_framebuffer = { - .validate = nv30_state_framebuffer_validate, +struct nvfx_state_entry nvfx_state_framebuffer = { + .validate = nvfx_state_framebuffer_validate, .dirty = { .pipe = NVFX_NEW_FB, .hw = NVFX_STATE_FB |