nv50: create blend stateobj
authorBen Skeggs <skeggsb@gmail.com>
Tue, 11 Mar 2008 15:56:10 +0000 (02:56 +1100)
committerBen Skeggs <skeggsb@gmail.com>
Tue, 11 Mar 2008 15:56:10 +0000 (02:56 +1100)
src/gallium/drivers/nv50/nv50_context.h
src/gallium/drivers/nv50/nv50_screen.c
src/gallium/drivers/nv50/nv50_state.c

index e2656bd..6096818 100644 (file)
 #define NOUVEAU_MSG(fmt, args...) \
        fprintf(stderr, "nouveau: "fmt, ##args);
 
+#define NV50_NEW_BLEND (1 << 0)
+
+struct nv50_blend_stateobj {
+       struct pipe_blend_state pipe;
+       struct nouveau_stateobj *so;
+};
+
 struct nv50_context {
        struct pipe_context pipe;
 
@@ -29,8 +36,16 @@ struct nv50_context {
        unsigned pctx_id;
 
        struct draw_context *draw;
+
+       unsigned dirty;
+       struct nv50_blend_stateobj *blend;
 };
 
+static INLINE struct nv50_context *
+nv50_context(struct pipe_context *pipe)
+{
+       return (struct nv50_context *)pipe;
+}
 
 extern void nv50_init_miptree_functions(struct nv50_context *nv50);
 extern void nv50_init_surface_functions(struct nv50_context *nv50);
index f8fd11d..62c23c7 100644 (file)
@@ -103,6 +103,7 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws,
        struct nv50_screen *screen = CALLOC_STRUCT(nv50_screen);
        struct nouveau_stateobj *so;
        unsigned tesla_class = 0, ret;
+       int i;
 
        if (!screen)
                return NULL;
@@ -146,6 +147,15 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws,
        so = so_new(128, 0);
        so_method(so, screen->tesla, NV50TCL_DMA_NOTIFY, 1);
        so_data  (so, screen->sync->handle);
+       so_method(so, screen->tesla, NV50TCL_DMA_IN_MEMORY0(0),
+                 NV50TCL_DMA_IN_MEMORY0__SIZE);
+       for (i = 0; i < NV50TCL_DMA_IN_MEMORY0__SIZE; i++)
+               so_data(so, nvws->channel->vram->handle);
+       so_method(so, screen->tesla, NV50TCL_DMA_IN_MEMORY1(0),
+                 NV50TCL_DMA_IN_MEMORY1__SIZE);
+       for (i = 0; i < NV50TCL_DMA_IN_MEMORY1__SIZE; i++)
+               so_data(so, nvws->channel->vram->handle);
+
        so_emit(nvws, so);
        so_ref(NULL, &so);
        nvws->push_flush(nvws->channel, 0);
index 99dcab5..7a01100 100644 (file)
@@ -5,21 +5,81 @@
 #include "nv50_context.h"
 #include "nv50_state.h"
 
+#include "nouveau/nouveau_stateobj.h"
+
 static void *
 nv50_blend_state_create(struct pipe_context *pipe,
                        const struct pipe_blend_state *cso)
 {
-       return NULL;
+       struct nouveau_stateobj *so = so_new(64, 0);
+       struct nouveau_grobj *tesla = nv50_context(pipe)->screen->tesla;
+       struct nv50_blend_stateobj *bso = CALLOC_STRUCT(nv50_blend_stateobj);
+       unsigned cmask = 0, i;
+
+       /*XXX ignored:
+        *      - dither
+        */
+
+       if (cso->blend_enable == 0) {
+               so_method(so, tesla, NV50TCL_BLEND_ENABLE(0), 8);
+               for (i = 0; i < 8; i++)
+                       so_data(so, 0);
+       } else {
+               so_method(so, tesla, NV50TCL_BLEND_ENABLE(0), 8);
+               for (i = 0; i < 8; i++)
+                       so_data(so, 1);
+               so_method(so, tesla, NV50TCL_BLEND_EQUATION_RGB, 5);
+               so_data  (so, nvgl_blend_eqn(cso->rgb_func));
+               so_data  (so, nvgl_blend_func(cso->rgb_src_factor));
+               so_data  (so, nvgl_blend_func(cso->rgb_dst_factor));
+               so_data  (so, nvgl_blend_eqn(cso->alpha_func));
+               so_data  (so, nvgl_blend_func(cso->alpha_src_factor));
+               so_method(so, tesla, NV50TCL_BLEND_FUNC_DST_ALPHA, 1);
+               so_data  (so, nvgl_blend_func(cso->alpha_dst_factor));
+       }
+
+       if (cso->logicop_enable == 0 ) {
+               so_method(so, tesla, NV50TCL_LOGIC_OP_ENABLE, 1);
+               so_data  (so, 0);
+       } else {
+               so_method(so, tesla, NV50TCL_LOGIC_OP_ENABLE, 2);
+               so_data  (so, 1);
+               so_data  (so, nvgl_logicop_func(cso->logicop_func));
+       }
+
+       if (cso->colormask & PIPE_MASK_R)
+               cmask |= (1 << 0);
+       if (cso->colormask & PIPE_MASK_G)
+               cmask |= (1 << 4);
+       if (cso->colormask & PIPE_MASK_B)
+               cmask |= (1 << 8);
+       if (cso->colormask & PIPE_MASK_A)
+               cmask |= (1 << 12);
+       so_method(so, tesla, NV50TCL_COLOR_MASK(0), 8);
+       for (i = 0; i < 8; i++)
+               so_data(so, cmask);
+
+       bso->pipe = *cso;
+       so_ref(so, &bso->so);
+       return (void *)bso;
 }
 
 static void
 nv50_blend_state_bind(struct pipe_context *pipe, void *hwcso)
 {
+       struct nv50_context *nv50 = nv50_context(pipe);
+
+       nv50->blend = hwcso;
+       nv50->dirty |= NV50_NEW_BLEND;
 }
 
 static void
 nv50_blend_state_delete(struct pipe_context *pipe, void *hwcso)
 {
+       struct nv50_blend_stateobj *bso = hwcso;
+
+       so_ref(NULL, &bso->so);
+       FREE(bso);
 }
 
 static void *