r300-gallium: Enable all four colorbuffer render targets.
[mesa.git] / src / gallium / drivers / r300 / r300_screen.c
index 5074e3e6fa473c7e4b685c91889a15dd8353d47f..5088c130392978eac35847e0d8afbadb26af7c89 100644 (file)
 
 #include "r300_screen.h"
 
-static const char* r300_get_vendor(struct pipe_screen* pscreen) {
+/* Return the identifier behind whom the brave coders responsible for this
+ * amalgamation of code, sweat, and duct tape, routinely obscure their names.
+ *
+ * ...I should have just put "Corbin Simpson", but I'm not that cool.
+ *
+ * (Or egotistical. Yet.) */
+static const char* r300_get_vendor(struct pipe_screen* pscreen)
+{
     return "X.Org R300 Project";
 }
 
-static const char* r300_get_name(struct pipe_screen* pscreen) {
-    /* XXX lazy */
-    return "unknown";
+static const char* chip_families[] = {
+    "R300",
+    "R350",
+    "R360",
+    "RV350",
+    "RV370",
+    "RV380",
+    "R420",
+    "R423",
+    "R430",
+    "R480",
+    "R481",
+    "RV410",
+    "RS400",
+    "RC410",
+    "RS480",
+    "RS482",
+    "RS690",
+    "RS740",
+    "RV515",
+    "R520",
+    "RV530",
+    "R580",
+    "RV560",
+    "RV570"
+};
+
+static const char* r300_get_name(struct pipe_screen* pscreen)
+{
+    struct r300_screen* r300screen = r300_screen(pscreen);
+
+    return chip_families[r300screen->caps->family];
 }
 
-static int r300_get_param(struct pipe_screen* pscreen, int param) {
+static int r300_get_param(struct pipe_screen* pscreen, int param)
+{
     struct r300_screen* r300screen = r300_screen(pscreen);
 
     switch (param) {
@@ -43,16 +80,18 @@ static int r300_get_param(struct pipe_screen* pscreen, int param) {
         case PIPE_CAP_NPOT_TEXTURES:
             /* IN THEORY */
             return 0;
-        case PIPE_CAP_S3TC:
+        case PIPE_CAP_TWO_SIDED_STENCIL:
+            if (r300screen->caps->is_r500) {
+                return 1;
+            } else {
+                return 0;
+            }
+            return 0;
+        case PIPE_CAP_GLSL:
             /* IN THEORY */
             return 0;
-        case PIPE_CAP_TWO_SIDED_STENCIL:
+        case PIPE_CAP_S3TC:
             /* IN THEORY */
-            /* if (r300screen->is_r500) {
-             * return 1;
-             * } else {
-             * return 0;
-             * } */
             return 0;
         case PIPE_CAP_ANISOTROPIC_FILTER:
             /* IN THEORY */
@@ -60,62 +99,113 @@ static int r300_get_param(struct pipe_screen* pscreen, int param) {
         case PIPE_CAP_POINT_SPRITE:
             /* IN THEORY */
             return 0;
+        case PIPE_CAP_MAX_RENDER_TARGETS:
+            return 4;
         case PIPE_CAP_OCCLUSION_QUERY:
             /* IN THEORY */
             return 0;
         case PIPE_CAP_TEXTURE_SHADOW_MAP:
             /* IN THEORY */
             return 0;
-        case PIPE_CAP_GLSL:
-            /* IN THEORY */
-            return 0;
         case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
-            /* 12 == 2048x2048 */
-            if (r300screen->is_r500) {
-                /* R500 can do 4096x4096 */
+            if (r300screen->caps->is_r500) {
+                /* 13 == 4096x4096 */
                 return 13;
             } else {
+                /* 12 == 2048x2048 */
                 return 12;
             }
         case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
-            /* XXX educated guess */
-            return 8;
+            /* So, technically, the limit is the same as above, but some math
+             * shows why this is silly. Assuming RGBA, 4cpp, we can see that
+             * 4096*4096*4096 = 64.0 GiB exactly, so it's not exactly
+             * practical. However, if at some point a game really wants this,
+             * then we can remove this limit. */
+            if (r300screen->caps->is_r500) {
+                /* 9 == 256x256x256 */
+                return 9;
+            } else {
+                /* 8 == 128*128*128 */
+                return 8;
+            }
         case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
-            /* XXX educated guess */
-            return 11;
-        case PIPE_CAP_MAX_RENDER_TARGETS:
-            /* XXX 4 eventually */
+            if (r300screen->caps->is_r500) {
+                /* 13 == 4096x4096 */
+                return 13;
+            } else {
+                /* 12 == 2048x2048 */
+                return 12;
+            }
+        case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
+            return 1;
+        case PIPE_CAP_TEXTURE_MIRROR_REPEAT:
             return 1;
+        case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS:
+            /* XXX guessing */
+            return 2;
         default:
+            debug_printf("r300: Implementation error: Bad param %d\n",
+                param);
             return 0;
     }
 }
 
-static float r300_get_paramf(struct pipe_screen* pscreen, int param) {
+static float r300_get_paramf(struct pipe_screen* pscreen, int param)
+{
     switch (param) {
         case PIPE_CAP_MAX_LINE_WIDTH:
         case PIPE_CAP_MAX_LINE_WIDTH_AA:
-            /* XXX look this up, lazy ass! */
-            return 0.0;
+            /* XXX this is the biggest thing that will fit in that register.
+            * Perhaps the actual rendering limits are less? */
+            return 10922.0f;
         case PIPE_CAP_MAX_POINT_WIDTH:
         case PIPE_CAP_MAX_POINT_WIDTH_AA:
-            /* XXX see above */
-            return 255.0;
+            /* XXX this is the biggest thing that will fit in that register.
+             * Perhaps the actual rendering limits are less? */
+            return 10922.0f;
         case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
-            return 16.0;
+            return 16.0f;
         case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
-            return 16.0;
+            return 16.0f;
         default:
-            return 0.0;
+            debug_printf("r300: Implementation error: Bad paramf %d\n",
+                param);
+            return 0.0f;
     }
 }
 
+/* XXX moar formats */
+static boolean check_tex_2d_format(enum pipe_format format)
+{
+    switch (format) {
+        case PIPE_FORMAT_A8R8G8B8_UNORM:
+        case PIPE_FORMAT_I8_UNORM:
+            return TRUE;
+        default:
+            debug_printf("r300: Warning: Got unknown format: %s, in %s\n",
+                pf_name(format), __FUNCTION__);
+            break;
+    }
+
+    return FALSE;
+}
+
+/* XXX moar targets */
 static boolean r300_is_format_supported(struct pipe_screen* pscreen,
                                         enum pipe_format format,
                                         enum pipe_texture_target target,
                                         unsigned tex_usage,
                                         unsigned geom_flags)
 {
+    switch (target) {
+        case PIPE_TEXTURE_2D:
+            return check_tex_2d_format(format);
+        default:
+            debug_printf("r300: Warning: Got unknown format target: %d\n",
+                format);
+            break;
+    }
+
     return FALSE;
 }
 
@@ -123,8 +213,8 @@ static void* r300_surface_map(struct pipe_screen* screen,
                               struct pipe_surface* surface,
                               unsigned flags)
 {
-    /* XXX this is not quite right */
-    char* map = pipe_buffer_map(screen, surface->buffer, flags);
+    struct r300_texture* tex = (struct r300_texture*)surface->texture;
+    char* map = pipe_buffer_map(screen, tex->buffer, flags);
 
     if (!map) {
         return NULL;
@@ -136,28 +226,33 @@ static void* r300_surface_map(struct pipe_screen* screen,
 static void r300_surface_unmap(struct pipe_screen* screen,
                                struct pipe_surface* surface)
 {
-    pipe_buffer_unmap(screen, surface->buffer);
+    struct r300_texture* tex = (struct r300_texture*)surface->texture;
+    pipe_buffer_unmap(screen, tex->buffer);
 }
 
-static void r300_destroy_screen(struct pipe_screen* pscreen) {
-    FREE(pscreen);
+static void r300_destroy_screen(struct pipe_screen* pscreen)
+{
+    struct r300_screen* r300screen = r300_screen(pscreen);
+
+    FREE(r300screen->caps);
+    FREE(r300screen);
 }
 
-struct pipe_screen* r300_create_screen(struct pipe_winsys* winsys, uint pci_id) {
+struct pipe_screen* r300_create_screen(struct pipe_winsys* winsys,
+                                       struct r300_winsys* r300_winsys)
+{
     struct r300_screen* r300screen = CALLOC_STRUCT(r300_screen);
+    struct r300_capabilities* caps = CALLOC_STRUCT(r300_capabilities);
 
-    if (!r300screen)
+    if (!r300screen || !caps)
         return NULL;
 
-    /* XXX break this into its own function?
-    switch (pci_id) {
-        default:
-            debug_printf("%s: unknown PCI ID 0x%x, cannot create screen!\n",
-                         __FUNCTION__, pci_id);
-            return NULL;
-    } */
+    caps->pci_id = r300_winsys->pci_id;
+    caps->num_frag_pipes = r300_winsys->gb_pipes;
 
-    r300screen->pci_id = pci_id;
+    r300_parse_chipset(caps);
+
+    r300screen->caps = caps;
     r300screen->screen.winsys = winsys;
     r300screen->screen.destroy = r300_destroy_screen;
     r300screen->screen.get_name = r300_get_name;
@@ -168,5 +263,8 @@ struct pipe_screen* r300_create_screen(struct pipe_winsys* winsys, uint pci_id)
     r300screen->screen.surface_map = r300_surface_map;
     r300screen->screen.surface_unmap = r300_surface_unmap;
 
+    r300_init_screen_texture_functions(&r300screen->screen);
+    u_simple_screen_init(&r300screen->screen);
+
     return &r300screen->screen;
 }