nouveau: remove useless NOUVEAU_BO_SWIZZLED flag, copy/paste nv40 work to swizzle...
[mesa.git] / src / gallium / drivers / nv30 / nv30_screen.c
index 3ca50e4fbf46d24707917b43c0638176714a5267..910a3c456dd288679b538027f80de1878eae23c0 100644 (file)
@@ -1,27 +1,31 @@
 #include "pipe/p_screen.h"
-#include "pipe/p_util.h"
 
 #include "nv30_context.h"
 #include "nv30_screen.h"
 
+#define NV30TCL_CHIPSET_3X_MASK 0x00000003
+#define NV34TCL_CHIPSET_3X_MASK 0x00000010
+#define NV35TCL_CHIPSET_3X_MASK 0x000001e0
+
 static const char *
-nv30_screen_get_name(struct pipe_screen *screen)
+nv30_screen_get_name(struct pipe_screen *pscreen)
 {
-       struct nv30_screen *nv30screen = nv30_screen(screen);
+       struct nv30_screen *screen = nv30_screen(pscreen);
+       struct nouveau_device *dev = screen->nvws->channel->device;
        static char buffer[128];
 
-       snprintf(buffer, sizeof(buffer), "NV%02X", nv30screen->chipset);
+       snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset);
        return buffer;
 }
 
 static const char *
-nv30_screen_get_vendor(struct pipe_screen *screen)
+nv30_screen_get_vendor(struct pipe_screen *pscreen)
 {
        return "nouveau";
 }
 
 static int
-nv30_screen_get_param(struct pipe_screen *screen, int param)
+nv30_screen_get_param(struct pipe_screen *pscreen, int param)
 {
        switch (param) {
        case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
@@ -50,6 +54,13 @@ nv30_screen_get_param(struct pipe_screen *screen, int param)
                return 10;
        case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
                return 13;
+       case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
+               return 0;
+       case PIPE_CAP_TEXTURE_MIRROR_REPEAT:
+               return 1;
+       case NOUVEAU_CAP_HW_VTXBUF:
+       case NOUVEAU_CAP_HW_IDXBUF:
+               return 1;
        default:
                NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
                return 0;
@@ -57,7 +68,7 @@ nv30_screen_get_param(struct pipe_screen *screen, int param)
 }
 
 static float
-nv30_screen_get_paramf(struct pipe_screen *screen, int param)
+nv30_screen_get_paramf(struct pipe_screen *pscreen, int param)
 {
        switch (param) {
        case PIPE_CAP_MAX_LINE_WIDTH:
@@ -67,11 +78,9 @@ nv30_screen_get_paramf(struct pipe_screen *screen, int param)
        case PIPE_CAP_MAX_POINT_WIDTH_AA:
                return 64.0;
        case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
-               return 16.0;
+               return 8.0;
        case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
                return 4.0;
-       case PIPE_CAP_BITMAP_TEXCOORD_BIAS:
-               return 0.0;
        default:
                NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
                return 0.0;
@@ -79,11 +88,12 @@ nv30_screen_get_paramf(struct pipe_screen *screen, int param)
 }
 
 static boolean
-nv30_screen_is_format_supported(struct pipe_screen *screen,
-                               enum pipe_format format, uint type)
+nv30_screen_surface_format_supported(struct pipe_screen *pscreen,
+                                    enum pipe_format format,
+                                    enum pipe_texture_target target,
+                                    unsigned tex_usage, unsigned geom_flags)
 {
-       switch (type) {
-       case PIPE_SURFACE:
+       if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) {
                switch (format) {
                case PIPE_FORMAT_A8R8G8B8_UNORM:
                case PIPE_FORMAT_R5G6B5_UNORM: 
@@ -93,62 +103,281 @@ nv30_screen_is_format_supported(struct pipe_screen *screen,
                default:
                        break;
                }
-               break;
-       case PIPE_TEXTURE:
+       } else {
                switch (format) {
                case PIPE_FORMAT_A8R8G8B8_UNORM:
                case PIPE_FORMAT_A1R5G5B5_UNORM:
                case PIPE_FORMAT_A4R4G4B4_UNORM:
                case PIPE_FORMAT_R5G6B5_UNORM: 
-               case PIPE_FORMAT_U_L8:
-               case PIPE_FORMAT_U_A8:
-               case PIPE_FORMAT_U_I8:
-               case PIPE_FORMAT_U_A8_L8:
+               case PIPE_FORMAT_L8_UNORM:
+               case PIPE_FORMAT_A8_UNORM:
+               case PIPE_FORMAT_I8_UNORM:
+               case PIPE_FORMAT_A8L8_UNORM:
                case PIPE_FORMAT_Z16_UNORM:
                case PIPE_FORMAT_Z24S8_UNORM:
                        return TRUE;
                default:
                        break;
                }
-               break;
-       default:
-               assert(0);
-       };
+       }
 
        return FALSE;
 }
 
+static void *
+nv30_surface_map(struct pipe_screen *screen, struct pipe_surface *surface,
+                unsigned flags )
+{
+       struct pipe_winsys      *ws = screen->winsys;
+       struct pipe_surface     *surface_to_map;
+       void                    *map;
+
+       if (!(surface->texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) {
+               struct nv30_miptree *mt = (struct nv30_miptree *)surface->texture;
+
+               if (!mt->shadow_tex) {
+                       unsigned old_tex_usage = surface->texture->tex_usage;
+                       surface->texture->tex_usage = NOUVEAU_TEXTURE_USAGE_LINEAR;
+                       mt->shadow_tex = screen->texture_create(screen, surface->texture);
+                       surface->texture->tex_usage = old_tex_usage;
+
+                       assert(mt->shadow_tex->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR);
+                       mt->shadow_surface = screen->get_tex_surface
+                       (
+                               screen, mt->shadow_tex,
+                               surface->face, surface->level, surface->zslice,
+                               surface->usage
+                       );
+               }
+
+               surface_to_map = mt->shadow_surface;
+       }
+       else
+               surface_to_map = surface;
+
+       assert(surface_to_map);
+
+       map = ws->buffer_map(ws, surface_to_map->buffer, flags);
+       if (!map)
+               return NULL;
+
+       return map + surface_to_map->offset;
+}
+
+static void
+nv30_surface_unmap(struct pipe_screen *screen, struct pipe_surface *surface)
+{
+       struct pipe_winsys      *ws = screen->winsys;
+       struct pipe_surface     *surface_to_unmap;
+
+       /* TODO: Copy from shadow just before push buffer is flushed instead.
+                There are probably some programs that map/unmap excessively
+                before rendering. */
+       if (!(surface->texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) {
+               struct nv30_miptree *mt = (struct nv30_miptree *)surface->texture;
+
+               assert(mt->shadow_tex);
+
+               surface_to_unmap = mt->shadow_surface;
+       }
+       else
+               surface_to_unmap = surface;
+
+       assert(surface_to_unmap);
+
+       ws->buffer_unmap(ws, surface_to_unmap->buffer);
+
+       if (surface_to_unmap != surface) {
+               struct nv30_screen *nvscreen = nv30_screen(screen);
+
+               nvscreen->nvws->surface_copy(nvscreen->nvws,
+                                            surface, 0, 0,
+                                            surface_to_unmap, 0, 0,
+                                            surface->width, surface->height);
+       }
+}
+
 static void
-nv30_screen_destroy(struct pipe_screen *screen)
+nv30_screen_destroy(struct pipe_screen *pscreen)
 {
-       FREE(screen);
+       struct nv30_screen *screen = nv30_screen(pscreen);
+       struct nouveau_winsys *nvws = screen->nvws;
+
+       nvws->res_free(&screen->vp_exec_heap);
+       nvws->res_free(&screen->vp_data_heap);
+       nvws->res_free(&screen->query_heap);
+       nvws->notifier_free(&screen->query);
+       nvws->notifier_free(&screen->sync);
+       nvws->grobj_free(&screen->rankine);
+
+       FREE(pscreen);
 }
 
 struct pipe_screen *
-nv30_screen_create(struct pipe_winsys *winsys, struct nouveau_winsys *nvws,
-                  unsigned chipset)
+nv30_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)
 {
-       struct nv30_screen *nv30screen = CALLOC_STRUCT(nv30_screen);
+       struct nv30_screen *screen = CALLOC_STRUCT(nv30_screen);
+       struct nouveau_stateobj *so;
+       unsigned rankine_class = 0;
+       unsigned chipset = nvws->channel->device->chipset;
+       int ret, i;
+
+       if (!screen)
+               return NULL;
+       screen->nvws = nvws;
+
+       /* 3D object */
+       switch (chipset & 0xf0) {
+       case 0x30:
+               if (NV30TCL_CHIPSET_3X_MASK & (1 << (chipset & 0x0f)))
+                       rankine_class = 0x0397;
+               else
+               if (NV34TCL_CHIPSET_3X_MASK & (1 << (chipset & 0x0f)))
+                       rankine_class = 0x0697;
+               else
+               if (NV35TCL_CHIPSET_3X_MASK & (1 << (chipset & 0x0f)))
+                       rankine_class = 0x0497;
+               break;
+       default:
+               break;
+       }
+
+       if (!rankine_class) {
+               NOUVEAU_ERR("Unknown nv3x chipset: nv%02x\n", chipset);
+               return NULL;
+       }
+
+       ret = nvws->grobj_alloc(nvws, rankine_class, &screen->rankine);
+       if (ret) {
+               NOUVEAU_ERR("Error creating 3D object: %d\n", ret);
+               return FALSE;
+       }
+
+       /* Notifier for sync purposes */
+       ret = nvws->notifier_alloc(nvws, 1, &screen->sync);
+       if (ret) {
+               NOUVEAU_ERR("Error creating notifier object: %d\n", ret);
+               nv30_screen_destroy(&screen->pipe);
+               return NULL;
+       }
+
+       /* Query objects */
+       ret = nvws->notifier_alloc(nvws, 32, &screen->query);
+       if (ret) {
+               NOUVEAU_ERR("Error initialising query objects: %d\n", ret);
+               nv30_screen_destroy(&screen->pipe);
+               return NULL;
+       }
 
-       if (!nv30screen)
+       ret = nvws->res_init(&screen->query_heap, 0, 32);
+       if (ret) {
+               NOUVEAU_ERR("Error initialising query object heap: %d\n", ret);
+               nv30_screen_destroy(&screen->pipe);
                return NULL;
+       }
+
+       /* Vtxprog resources */
+       if (nvws->res_init(&screen->vp_exec_heap, 0, 256) ||
+           nvws->res_init(&screen->vp_data_heap, 0, 256)) {
+               nv30_screen_destroy(&screen->pipe);
+               return NULL;
+       }
+
+       /* Static rankine initialisation */
+       so = so_new(128, 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);
+       so_data  (so, nvws->channel->vram->handle);
+       so_data  (so, nvws->channel->gart->handle);
+       so_method(so, screen->rankine, NV34TCL_DMA_COLOR1, 1);
+       so_data  (so, nvws->channel->vram->handle);
+       so_method(so, screen->rankine, NV34TCL_DMA_COLOR0, 2);
+       so_data  (so, nvws->channel->vram->handle);
+       so_data  (so, nvws->channel->vram->handle);
+       so_method(so, screen->rankine, NV34TCL_DMA_VTXBUF0, 2);
+       so_data  (so, nvws->channel->vram->handle);
+       so_data  (so, nvws->channel->gart->handle);
+/*     so_method(so, screen->rankine, NV34TCL_DMA_FENCE, 2);
+       so_data  (so, 0);
+       so_data  (so, screen->query->handle);*/
+       so_method(so, screen->rankine, NV34TCL_DMA_IN_MEMORY7, 1);
+       so_data  (so, nvws->channel->vram->handle);
+       so_method(so, screen->rankine, NV34TCL_DMA_IN_MEMORY8, 1);
+       so_data  (so, nvws->channel->vram->handle);
+
+       for (i=1; i<8; i++) {
+               so_method(so, screen->rankine, NV34TCL_VIEWPORT_CLIP_HORIZ(i), 1);
+               so_data  (so, 0);
+               so_method(so, screen->rankine, NV34TCL_VIEWPORT_CLIP_VERT(i), 1);
+               so_data  (so, 0);
+       }
+
+       so_method(so, screen->rankine, 0x220, 1);
+       so_data  (so, 1);
+
+       so_method(so, screen->rankine, 0x03b0, 1);
+       so_data  (so, 0x00100000);
+       so_method(so, screen->rankine, 0x1454, 1);
+       so_data  (so, 0);
+       so_method(so, screen->rankine, 0x1d80, 1);
+       so_data  (so, 3);
+       so_method(so, screen->rankine, 0x1450, 1);
+       so_data  (so, 0x00030004);
+       
+       /* NEW */
+       so_method(so, screen->rankine, 0x1e98, 1);
+       so_data  (so, 0);
+       so_method(so, screen->rankine, 0x17e0, 3);
+       so_data  (so, fui(0.0));
+       so_data  (so, fui(0.0));
+       so_data  (so, fui(1.0));
+       so_method(so, screen->rankine, 0x1f80, 16);
+       for (i=0; i<16; i++) {
+               so_data  (so, (i==8) ? 0x0000ffff : 0);
+       }
+
+       so_method(so, screen->rankine, 0x120, 3);
+       so_data  (so, 0);
+       so_data  (so, 1);
+       so_data  (so, 2);
+
+       so_method(so, screen->rankine, 0x1d88, 1);
+       so_data  (so, 0x00001200);
+
+       so_method(so, screen->rankine, NV34TCL_RC_ENABLE, 1);
+       so_data  (so, 0);
+
+       so_method(so, screen->rankine, NV34TCL_DEPTH_RANGE_NEAR, 2);
+       so_data  (so, fui(0.0));
+       so_data  (so, fui(1.0));
+
+       so_method(so, screen->rankine, NV34TCL_MULTISAMPLE_CONTROL, 1);
+       so_data  (so, 0xffff0000);
+
+       /* enables use of vp rather than fixed-function somehow */
+       so_method(so, screen->rankine, 0x1e94, 1);
+       so_data  (so, 0x13);
+
+       so_emit(nvws, so);
+       so_ref(NULL, &so);
+       nvws->push_flush(nvws, 0, NULL);
 
-       nv30screen->chipset = chipset;
-       nv30screen->nvws = nvws;
+       screen->pipe.winsys = ws;
+       screen->pipe.destroy = nv30_screen_destroy;
 
-       nv30screen->screen.winsys = winsys;
+       screen->pipe.get_name = nv30_screen_get_name;
+       screen->pipe.get_vendor = nv30_screen_get_vendor;
+       screen->pipe.get_param = nv30_screen_get_param;
+       screen->pipe.get_paramf = nv30_screen_get_paramf;
 
-       nv30screen->screen.destroy = nv30_screen_destroy;
+       screen->pipe.is_format_supported = nv30_screen_surface_format_supported;
 
-       nv30screen->screen.get_name = nv30_screen_get_name;
-       nv30screen->screen.get_vendor = nv30_screen_get_vendor;
-       nv30screen->screen.get_param = nv30_screen_get_param;
-       nv30screen->screen.get_paramf = nv30_screen_get_paramf;
-       nv30screen->screen.is_format_supported = 
-               nv30_screen_is_format_supported;
+       screen->pipe.surface_map = nv30_surface_map;
+       screen->pipe.surface_unmap = nv30_surface_unmap;
 
-       nv30_screen_init_miptree_functions(&nv30screen->screen);
+       nv30_screen_init_miptree_functions(&screen->pipe);
 
-       return &nv30screen->screen;
+       return &screen->pipe;
 }