nouveau: remove useless NOUVEAU_BO_SWIZZLED flag, copy/paste nv40 work to swizzle...
[mesa.git] / src / gallium / drivers / nv30 / nv30_screen.c
index 9c576369891dbb74b3e25d91f245a779ead2d88b..910a3c456dd288679b538027f80de1878eae23c0 100644 (file)
@@ -1,5 +1,4 @@
 #include "pipe/p_screen.h"
-#include "pipe/p_util.h"
 
 #include "nv30_context.h"
 #include "nv30_screen.h"
@@ -55,9 +54,13 @@ nv30_screen_get_param(struct pipe_screen *pscreen, 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 0;
+               return 1;
        default:
                NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
                return 0;
@@ -75,7 +78,7 @@ nv30_screen_get_paramf(struct pipe_screen *pscreen, 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;
        default:
@@ -86,10 +89,11 @@ nv30_screen_get_paramf(struct pipe_screen *pscreen, int param)
 
 static boolean
 nv30_screen_surface_format_supported(struct pipe_screen *pscreen,
-                                    enum pipe_format format, uint type)
+                                    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: 
@@ -99,8 +103,7 @@ nv30_screen_surface_format_supported(struct pipe_screen *pscreen,
                default:
                        break;
                }
-               break;
-       case PIPE_TEXTURE:
+       } else {
                switch (format) {
                case PIPE_FORMAT_A8R8G8B8_UNORM:
                case PIPE_FORMAT_A1R5G5B5_UNORM:
@@ -116,10 +119,7 @@ nv30_screen_surface_format_supported(struct pipe_screen *pscreen,
                default:
                        break;
                }
-               break;
-       default:
-               assert(0);
-       };
+       }
 
        return FALSE;
 }
@@ -128,22 +128,73 @@ static void *
 nv30_surface_map(struct pipe_screen *screen, struct pipe_surface *surface,
                 unsigned flags )
 {
-       struct pipe_winsys *ws = screen->winsys;
-       void *map;
+       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->buffer, flags);
+       map = ws->buffer_map(ws, surface_to_map->buffer, flags);
        if (!map)
                return NULL;
 
-       return map + surface->offset;
+       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_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);
 
-       ws->buffer_unmap(ws, surface->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