#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"
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)
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)
{
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 )
{
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:
enum pipe_texture_target target,
unsigned sample_count,
unsigned bindings,
- boolean srgb)
+ boolean srgb,
+ boolean bypass_check)
{
enum pipe_format result;
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
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)
{
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;
}
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;
}
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;