st/nine: Integrate nine_pipe_context_clear to nine_context_clear
[mesa.git] / src / gallium / state_trackers / nine / nine_pipe.h
index 43a7737cdf982a6a3535d14905b5ef8ba7464f05..6bd4a0c89720026cc5911358e378631743b1341f 100644 (file)
@@ -27,6 +27,7 @@
 #include "pipe/p_format.h"
 #include "pipe/p_screen.h"
 #include "pipe/p_state.h" /* pipe_box */
+#include "util/macros.h"
 #include "util/u_rect.h"
 #include "util/u_format.h"
 #include "nine_helpers.h"
@@ -36,39 +37,12 @@ struct cso_context;
 extern const enum pipe_format nine_d3d9_to_pipe_format_map[120];
 extern const D3DFORMAT nine_pipe_to_d3d9_format_map[PIPE_FORMAT_COUNT];
 
-void nine_convert_dsa_state(struct cso_context *, const DWORD *);
-void nine_convert_rasterizer_state(struct cso_context *, const DWORD *);
-void nine_convert_blend_state(struct cso_context *, const DWORD *);
+void nine_convert_dsa_state(struct pipe_depth_stencil_alpha_state *, const DWORD *);
+void nine_convert_rasterizer_state(struct NineDevice9 *, struct pipe_rasterizer_state *, const DWORD *);
+void nine_convert_blend_state(struct pipe_blend_state *, const DWORD *);
 void nine_convert_sampler_state(struct cso_context *, int idx, const DWORD *);
 
-void nine_pipe_context_clear(struct NineDevice9 *);
-
-static inline unsigned d3dlock_buffer_to_pipe_transfer_usage(DWORD Flags)
-{
-    unsigned usage;
-
-    if (Flags & D3DLOCK_DISCARD)
-        usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE;
-    else
-    if (Flags & D3DLOCK_READONLY)
-        usage = PIPE_TRANSFER_READ;
-    else
-        usage = PIPE_TRANSFER_READ_WRITE;
-
-    if (Flags & D3DLOCK_NOOVERWRITE)
-        usage = (PIPE_TRANSFER_UNSYNCHRONIZED |
-                 PIPE_TRANSFER_DISCARD_RANGE | usage) & ~PIPE_TRANSFER_READ;
-    else
-    if (Flags & D3DLOCK_DONOTWAIT)
-        usage |= PIPE_TRANSFER_DONTBLOCK;
-
-    /*
-    if (Flags & D3DLOCK_NO_DIRTY_UPDATE)
-        usage |= PIPE_TRANSFER_FLUSH_EXPLICIT;
-    */
-
-    return usage;
-}
+#define is_ATI1_ATI2(format) (format == PIPE_FORMAT_RGTC1_UNORM || format == PIPE_FORMAT_RGTC2_UNORM)
 
 static inline void
 rect_to_pipe_box(struct pipe_box *dst, const RECT *src)
@@ -81,6 +55,49 @@ rect_to_pipe_box(struct pipe_box *dst, const RECT *src)
     dst->depth = 1;
 }
 
+static inline void
+pipe_box_to_rect(RECT *dst, const struct pipe_box *src)
+{
+    dst->left = src->x;
+    dst->right = src->x + src->width;
+    dst->top = src->y;
+    dst->bottom = src->y + src->height;
+}
+
+static inline void
+rect_minify_inclusive(RECT *rect)
+{
+    rect->left = rect->left >> 2;
+    rect->top = rect->top >> 2;
+    rect->right = DIV_ROUND_UP(rect->right, 2);
+    rect->bottom = DIV_ROUND_UP(rect->bottom, 2);
+}
+
+/* We suppose:
+ * 0 <= rect->left < rect->right
+ * 0 <= rect->top < rect->bottom
+ */
+static inline void
+fit_rect_format_inclusive(enum pipe_format format, RECT *rect, int width, int height)
+{
+    const unsigned w = util_format_get_blockwidth(format);
+    const unsigned h = util_format_get_blockheight(format);
+
+    if (util_format_is_compressed(format)) {
+        rect->left = rect->left - rect->left % w;
+        rect->top = rect->top - rect->top % h;
+        rect->right = (rect->right % w) == 0 ?
+            rect->right :
+            rect->right - (rect->right % w) + w;
+        rect->bottom = (rect->bottom % h) == 0 ?
+            rect->bottom :
+            rect->bottom - (rect->bottom % h) + h;
+    }
+
+    rect->right = MIN2(rect->right, width);
+    rect->bottom = MIN2(rect->bottom, height);
+}
+
 static inline boolean
 rect_to_pipe_box_clamp(struct pipe_box *dst, const RECT *src)
 {
@@ -164,6 +181,23 @@ pipe_to_d3d9_format(enum pipe_format format)
     return nine_pipe_to_d3d9_format_map[format];
 }
 
+/* ATI1 and ATI2 are not officially compressed in d3d9 */
+static inline boolean
+compressed_format( D3DFORMAT fmt )
+{
+    switch (fmt) {
+    case D3DFMT_DXT1:
+    case D3DFMT_DXT2:
+    case D3DFMT_DXT3:
+    case D3DFMT_DXT4:
+    case D3DFMT_DXT5:
+        return TRUE;
+    default:
+        break;
+    }
+    return FALSE;
+}
+
 static inline boolean
 depth_stencil_format( D3DFORMAT fmt )
 {
@@ -205,8 +239,7 @@ d3d9_get_pipe_depth_format_bindings(D3DFORMAT format)
     case D3DFMT_D32F_LOCKABLE:
     case D3DFMT_D16_LOCKABLE:
     case D3DFMT_D32_LOCKABLE:
-        return PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_TRANSFER_READ |
-               PIPE_BIND_TRANSFER_WRITE;
+        return PIPE_BIND_DEPTH_STENCIL;
     case D3DFMT_DF16:
     case D3DFMT_DF24:
     case D3DFMT_INTZ:
@@ -263,7 +296,8 @@ d3d9_to_pipe_format_checked(struct pipe_screen *screen,
                             enum pipe_texture_target target,
                             unsigned sample_count,
                             unsigned bindings,
-                            boolean srgb)
+                            boolean srgb,
+                            boolean bypass_check)
 {
     enum pipe_format result;
 
@@ -274,7 +308,11 @@ d3d9_to_pipe_format_checked(struct pipe_screen *screen,
     if (srgb)
         result = util_format_srgb(result);
 
-    if (format_check_internal(result))
+    /* bypass_check: Used for D3DPOOL_SCRATCH, which
+     * isn't limited to the formats supported by the
+     * device, and to check we are not using a format
+     * fallback. */
+    if (bypass_check || format_check_internal(result))
         return result;
 
     /* fallback to another format for formats
@@ -292,12 +330,77 @@ d3d9_to_pipe_format_checked(struct pipe_screen *screen,
         case D3DFMT_D24X8:
             if (format_check_internal(PIPE_FORMAT_Z24X8_UNORM))
                 return PIPE_FORMAT_Z24X8_UNORM;
+            break;
+        /* Support for X8L8V8U8 bumpenvmap format with lighting bits.
+         * X8L8V8U8 is commonly supported among dx9 cards.
+         * To avoid precision loss, we use PIPE_FORMAT_R32G32B32X32_FLOAT,
+         * however using PIPE_FORMAT_R8G8B8A8_SNORM should be ok */
+        case D3DFMT_X8L8V8U8:
+            if (bindings & PIPE_BIND_RENDER_TARGET)
+                return PIPE_FORMAT_NONE;
+            if (format_check_internal(PIPE_FORMAT_R32G32B32X32_FLOAT))
+                return PIPE_FORMAT_R32G32B32X32_FLOAT;
         default:
             break;
     }
     return PIPE_FORMAT_NONE;
 }
 
+/* The quality levels are vendor dependent, so we set our own.
+ * Every quality level has its own sample count and sample
+ * position matrix.
+ * The exact mapping might differ from system to system but thats OK,
+ * as there's no way to gather more information about quality levels
+ * in D3D9.
+ * In case of NONMASKABLE multisample map every quality-level
+ * to a MASKABLE MultiSampleType:
+ *  0: no MSAA
+ *  1: 2x MSAA
+ *  2: 4x MSAA
+ *  ...
+ *  If the requested quality level is not available to nearest
+ *  matching quality level is used.
+ *  If no multisample is available the function sets
+ *  multisample to D3DMULTISAMPLE_NONE and returns zero.
+ */
+static inline HRESULT
+d3dmultisample_type_check(struct pipe_screen *screen,
+                          D3DFORMAT format,
+                          D3DMULTISAMPLE_TYPE *multisample,
+                          DWORD multisamplequality,
+                          DWORD *levels)
+{
+    unsigned bind, i;
+
+    assert(multisample);
+
+    if (levels)
+        *levels = 1;
+
+    if (*multisample == D3DMULTISAMPLE_NONMASKABLE) {
+        if (depth_stencil_format(format))
+            bind = d3d9_get_pipe_depth_format_bindings(format);
+        else /* render-target */
+            bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
+
+        *multisample = 0;
+        for (i = D3DMULTISAMPLE_2_SAMPLES; i < D3DMULTISAMPLE_16_SAMPLES &&
+            multisamplequality; ++i) {
+            if (d3d9_to_pipe_format_checked(screen, format, PIPE_TEXTURE_2D,
+                    i, bind, FALSE, FALSE) != PIPE_FORMAT_NONE) {
+                multisamplequality--;
+                if (levels)
+                    (*levels)++;
+                *multisample = i;
+            }
+        }
+    }
+    /* Make sure to get an exact match */
+    if (multisamplequality)
+        return D3DERR_INVALIDCALL;
+    return D3D_OK;
+}
+
 static inline const char *
 d3dformat_to_string(D3DFORMAT fmt)
 {
@@ -375,6 +478,7 @@ d3dformat_to_string(D3DFORMAT fmt)
     case D3DFMT_NVDB: return "D3DFMT_NVDB";
     case D3DFMT_RESZ: return "D3DFMT_RESZ";
     case D3DFMT_NULL: return "D3DFMT_NULL";
+    case D3DFMT_ATOC: return "D3DFMT_ATOC";
     default:
         break;
     }
@@ -679,8 +783,16 @@ static inline unsigned nine_format_get_level_alloc_size(enum pipe_format format,
 
     w = u_minify(width, level);
     h = u_minify(height, level);
-    size = nine_format_get_stride(format, w) *
-        util_format_get_nblocksy(format, h);
+    if (is_ATI1_ATI2(format)) {
+        /* For "unknown" formats like ATIx use width * height bytes */
+        size = w * h;
+    } else if (format == PIPE_FORMAT_NONE) { /* D3DFMT_NULL */
+        size = w * h * 4;
+    } else {
+        size = nine_format_get_stride(format, w) *
+            util_format_get_nblocksy(format, h);
+    }
+
     return size;
 }
 
@@ -696,8 +808,13 @@ static inline unsigned nine_format_get_size_and_offsets(enum pipe_format format,
         w = u_minify(width, l);
         h = u_minify(height, l);
         offsets[l] = size;
-        size += nine_format_get_stride(format, w) *
-            util_format_get_nblocksy(format, h);
+        if (is_ATI1_ATI2(format)) {
+            /* For "unknown" formats like ATIx use width * height bytes */
+            size += w * h;
+        } else {
+            size += nine_format_get_stride(format, w) *
+                util_format_get_nblocksy(format, h);
+        }
     }
 
     return size;