17ec681f3Smrg/*
27ec681f3Smrg * Copyright 2011 Joakim Sindholt <opensource@zhasha.com>
37ec681f3Smrg *
47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
57ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
67ec681f3Smrg * to deal in the Software without restriction, including without limitation
77ec681f3Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub
87ec681f3Smrg * license, and/or sell copies of the Software, and to permit persons to whom
97ec681f3Smrg * the Software is furnished to do so, subject to the following conditions:
107ec681f3Smrg *
117ec681f3Smrg * The above copyright notice and this permission notice (including the next
127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the
137ec681f3Smrg * Software.
147ec681f3Smrg *
157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
187ec681f3Smrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
197ec681f3Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
207ec681f3Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
217ec681f3Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE. */
227ec681f3Smrg
237ec681f3Smrg#ifndef _NINE_PIPE_H_
247ec681f3Smrg#define _NINE_PIPE_H_
257ec681f3Smrg
267ec681f3Smrg#include "d3d9.h"
277ec681f3Smrg#include "pipe/p_format.h"
287ec681f3Smrg#include "pipe/p_screen.h"
297ec681f3Smrg#include "pipe/p_state.h" /* pipe_box */
307ec681f3Smrg#include "util/macros.h"
317ec681f3Smrg#include "util/u_rect.h"
327ec681f3Smrg#include "util/format/u_format.h"
337ec681f3Smrg#include "nine_helpers.h"
347ec681f3Smrg
357ec681f3Smrgstruct cso_context;
367ec681f3Smrg
377ec681f3Smrgextern const enum pipe_format nine_d3d9_to_pipe_format_map[120];
387ec681f3Smrgextern const D3DFORMAT nine_pipe_to_d3d9_format_map[PIPE_FORMAT_COUNT];
397ec681f3Smrg
407ec681f3Smrgvoid nine_convert_dsa_state(struct pipe_depth_stencil_alpha_state *, const DWORD *);
417ec681f3Smrgvoid nine_convert_rasterizer_state(struct NineDevice9 *, struct pipe_rasterizer_state *, const DWORD *);
427ec681f3Smrgvoid nine_convert_blend_state(struct pipe_blend_state *, const DWORD *);
437ec681f3Smrgvoid nine_convert_sampler_state(struct cso_context *, int idx, const DWORD *);
447ec681f3Smrg
457ec681f3Smrg#define is_ATI1_ATI2(format) (format == PIPE_FORMAT_RGTC1_UNORM || format == PIPE_FORMAT_RGTC2_UNORM)
467ec681f3Smrg
477ec681f3Smrgstatic inline void
487ec681f3Smrgrect_to_pipe_box(struct pipe_box *dst, const RECT *src)
497ec681f3Smrg{
507ec681f3Smrg    dst->x = src->left;
517ec681f3Smrg    dst->y = src->top;
527ec681f3Smrg    dst->z = 0;
537ec681f3Smrg    dst->width = src->right - src->left;
547ec681f3Smrg    dst->height = src->bottom - src->top;
557ec681f3Smrg    dst->depth = 1;
567ec681f3Smrg}
577ec681f3Smrg
587ec681f3Smrgstatic inline void
597ec681f3Smrgpipe_box_to_rect(RECT *dst, const struct pipe_box *src)
607ec681f3Smrg{
617ec681f3Smrg    dst->left = src->x;
627ec681f3Smrg    dst->right = src->x + src->width;
637ec681f3Smrg    dst->top = src->y;
647ec681f3Smrg    dst->bottom = src->y + src->height;
657ec681f3Smrg}
667ec681f3Smrg
677ec681f3Smrgstatic inline void
687ec681f3Smrgrect_minify_inclusive(RECT *rect)
697ec681f3Smrg{
707ec681f3Smrg    rect->left = rect->left >> 2;
717ec681f3Smrg    rect->top = rect->top >> 2;
727ec681f3Smrg    rect->right = DIV_ROUND_UP(rect->right, 2);
737ec681f3Smrg    rect->bottom = DIV_ROUND_UP(rect->bottom, 2);
747ec681f3Smrg}
757ec681f3Smrg
767ec681f3Smrg/* We suppose:
777ec681f3Smrg * 0 <= rect->left < rect->right
787ec681f3Smrg * 0 <= rect->top < rect->bottom
797ec681f3Smrg */
807ec681f3Smrgstatic inline void
817ec681f3Smrgfit_rect_format_inclusive(enum pipe_format format, RECT *rect, int width, int height)
827ec681f3Smrg{
837ec681f3Smrg    const unsigned w = util_format_get_blockwidth(format);
847ec681f3Smrg    const unsigned h = util_format_get_blockheight(format);
857ec681f3Smrg
867ec681f3Smrg    if (util_format_is_compressed(format)) {
877ec681f3Smrg        rect->left = rect->left - rect->left % w;
887ec681f3Smrg        rect->top = rect->top - rect->top % h;
897ec681f3Smrg        rect->right = (rect->right % w) == 0 ?
907ec681f3Smrg            rect->right :
917ec681f3Smrg            rect->right - (rect->right % w) + w;
927ec681f3Smrg        rect->bottom = (rect->bottom % h) == 0 ?
937ec681f3Smrg            rect->bottom :
947ec681f3Smrg            rect->bottom - (rect->bottom % h) + h;
957ec681f3Smrg    }
967ec681f3Smrg
977ec681f3Smrg    rect->right = MIN2(rect->right, width);
987ec681f3Smrg    rect->bottom = MIN2(rect->bottom, height);
997ec681f3Smrg}
1007ec681f3Smrg
1017ec681f3Smrgstatic inline boolean
1027ec681f3Smrgrect_to_pipe_box_clamp(struct pipe_box *dst, const RECT *src)
1037ec681f3Smrg{
1047ec681f3Smrg    rect_to_pipe_box(dst, src);
1057ec681f3Smrg
1067ec681f3Smrg    if (dst->width <= 0 || dst->height <= 0) {
1077ec681f3Smrg        DBG_FLAG(DBG_UNKNOWN, "Warning: NULL box");
1087ec681f3Smrg        dst->width = MAX2(dst->width, 0);
1097ec681f3Smrg        dst->height = MAX2(dst->height, 0);
1107ec681f3Smrg        return TRUE;
1117ec681f3Smrg    }
1127ec681f3Smrg    return FALSE;
1137ec681f3Smrg}
1147ec681f3Smrg
1157ec681f3Smrgstatic inline boolean
1167ec681f3Smrgrect_to_pipe_box_flip(struct pipe_box *dst, const RECT *src)
1177ec681f3Smrg{
1187ec681f3Smrg    rect_to_pipe_box(dst, src);
1197ec681f3Smrg
1207ec681f3Smrg    if (dst->width >= 0 && dst->height >= 0)
1217ec681f3Smrg        return FALSE;
1227ec681f3Smrg    if (dst->width < 0) dst->width = -dst->width;
1237ec681f3Smrg    if (dst->height < 0) dst->height = -dst->height;
1247ec681f3Smrg    return TRUE;
1257ec681f3Smrg}
1267ec681f3Smrg
1277ec681f3Smrgstatic inline void
1287ec681f3Smrgrect_to_pipe_box_xy_only(struct pipe_box *dst, const RECT *src)
1297ec681f3Smrg{
1307ec681f3Smrg    user_warn(src->left > src->right || src->top > src->bottom);
1317ec681f3Smrg
1327ec681f3Smrg    dst->x = src->left;
1337ec681f3Smrg    dst->y = src->top;
1347ec681f3Smrg    dst->width = src->right - src->left;
1357ec681f3Smrg    dst->height = src->bottom - src->top;
1367ec681f3Smrg}
1377ec681f3Smrg
1387ec681f3Smrgstatic inline boolean
1397ec681f3Smrgrect_to_pipe_box_xy_only_clamp(struct pipe_box *dst, const RECT *src)
1407ec681f3Smrg{
1417ec681f3Smrg    rect_to_pipe_box_xy_only(dst, src);
1427ec681f3Smrg
1437ec681f3Smrg    if (dst->width <= 0 || dst->height <= 0) {
1447ec681f3Smrg        DBG_FLAG(DBG_UNKNOWN, "Warning: NULL box");
1457ec681f3Smrg        dst->width = MAX2(dst->width, 0);
1467ec681f3Smrg        dst->height = MAX2(dst->height, 0);
1477ec681f3Smrg        return TRUE;
1487ec681f3Smrg    }
1497ec681f3Smrg    return FALSE;
1507ec681f3Smrg}
1517ec681f3Smrg
1527ec681f3Smrgstatic inline void
1537ec681f3Smrgrect_to_g3d_u_rect(struct u_rect *dst, const RECT *src)
1547ec681f3Smrg{
1557ec681f3Smrg    user_warn(src->left > src->right || src->top > src->bottom);
1567ec681f3Smrg
1577ec681f3Smrg    dst->x0 = src->left;
1587ec681f3Smrg    dst->x1 = src->right;
1597ec681f3Smrg    dst->y0 = src->top;
1607ec681f3Smrg    dst->y1 = src->bottom;
1617ec681f3Smrg}
1627ec681f3Smrg
1637ec681f3Smrgstatic inline void
1647ec681f3Smrgd3dbox_to_pipe_box(struct pipe_box *dst, const D3DBOX *src)
1657ec681f3Smrg{
1667ec681f3Smrg    user_warn(src->Left > src->Right);
1677ec681f3Smrg    user_warn(src->Top > src->Bottom);
1687ec681f3Smrg    user_warn(src->Front > src->Back);
1697ec681f3Smrg
1707ec681f3Smrg    dst->x = src->Left;
1717ec681f3Smrg    dst->y = src->Top;
1727ec681f3Smrg    dst->z = src->Front;
1737ec681f3Smrg    dst->width = src->Right - src->Left;
1747ec681f3Smrg    dst->height = src->Bottom - src->Top;
1757ec681f3Smrg    dst->depth = src->Back - src->Front;
1767ec681f3Smrg}
1777ec681f3Smrg
1787ec681f3Smrgstatic inline D3DFORMAT
1797ec681f3Smrgpipe_to_d3d9_format(enum pipe_format format)
1807ec681f3Smrg{
1817ec681f3Smrg    return nine_pipe_to_d3d9_format_map[format];
1827ec681f3Smrg}
1837ec681f3Smrg
1847ec681f3Smrgstatic inline boolean
1857ec681f3Smrgfetch4_compatible_format( D3DFORMAT fmt )
1867ec681f3Smrg{
1877ec681f3Smrg    /* Basically formats with only red channel are allowed (with some exceptions) */
1887ec681f3Smrg    static const D3DFORMAT allowed[] = { /* TODO: list incomplete */
1897ec681f3Smrg        D3DFMT_L8,
1907ec681f3Smrg        D3DFMT_L16,
1917ec681f3Smrg        D3DFMT_R16F,
1927ec681f3Smrg        D3DFMT_R32F,
1937ec681f3Smrg        D3DFMT_A8,
1947ec681f3Smrg        D3DFMT_DF16,
1957ec681f3Smrg        D3DFMT_DF24,
1967ec681f3Smrg        D3DFMT_INTZ
1977ec681f3Smrg    };
1987ec681f3Smrg    unsigned i;
1997ec681f3Smrg
2007ec681f3Smrg    for (i = 0; i < sizeof(allowed)/sizeof(D3DFORMAT); i++) {
2017ec681f3Smrg        if (fmt == allowed[i]) { return TRUE; }
2027ec681f3Smrg    }
2037ec681f3Smrg    return FALSE;
2047ec681f3Smrg}
2057ec681f3Smrg
2067ec681f3Smrg/* ATI1 and ATI2 are not officially compressed in d3d9 */
2077ec681f3Smrgstatic inline boolean
2087ec681f3Smrgcompressed_format( D3DFORMAT fmt )
2097ec681f3Smrg{
2107ec681f3Smrg    switch (fmt) {
2117ec681f3Smrg    case D3DFMT_DXT1:
2127ec681f3Smrg    case D3DFMT_DXT2:
2137ec681f3Smrg    case D3DFMT_DXT3:
2147ec681f3Smrg    case D3DFMT_DXT4:
2157ec681f3Smrg    case D3DFMT_DXT5:
2167ec681f3Smrg        return TRUE;
2177ec681f3Smrg    default:
2187ec681f3Smrg        break;
2197ec681f3Smrg    }
2207ec681f3Smrg    return FALSE;
2217ec681f3Smrg}
2227ec681f3Smrg
2237ec681f3Smrgstatic inline boolean
2247ec681f3Smrgdepth_stencil_format( D3DFORMAT fmt )
2257ec681f3Smrg{
2267ec681f3Smrg    static const D3DFORMAT allowed[] = {
2277ec681f3Smrg        D3DFMT_D16_LOCKABLE,
2287ec681f3Smrg        D3DFMT_D32,
2297ec681f3Smrg        D3DFMT_D15S1,
2307ec681f3Smrg        D3DFMT_D24S8,
2317ec681f3Smrg        D3DFMT_D24X8,
2327ec681f3Smrg        D3DFMT_D24X4S4,
2337ec681f3Smrg        D3DFMT_D16,
2347ec681f3Smrg        D3DFMT_D32F_LOCKABLE,
2357ec681f3Smrg        D3DFMT_D24FS8,
2367ec681f3Smrg        D3DFMT_D32_LOCKABLE,
2377ec681f3Smrg        D3DFMT_DF16,
2387ec681f3Smrg        D3DFMT_DF24,
2397ec681f3Smrg        D3DFMT_INTZ
2407ec681f3Smrg    };
2417ec681f3Smrg    unsigned i;
2427ec681f3Smrg
2437ec681f3Smrg    for (i = 0; i < sizeof(allowed)/sizeof(D3DFORMAT); i++) {
2447ec681f3Smrg        if (fmt == allowed[i]) { return TRUE; }
2457ec681f3Smrg    }
2467ec681f3Smrg    return FALSE;
2477ec681f3Smrg}
2487ec681f3Smrg
2497ec681f3Smrgstatic inline unsigned
2507ec681f3Smrgd3d9_get_pipe_depth_format_bindings(D3DFORMAT format)
2517ec681f3Smrg{
2527ec681f3Smrg    switch (format) {
2537ec681f3Smrg    case D3DFMT_D32:
2547ec681f3Smrg    case D3DFMT_D15S1:
2557ec681f3Smrg    case D3DFMT_D24S8:
2567ec681f3Smrg    case D3DFMT_D24X8:
2577ec681f3Smrg    case D3DFMT_D24X4S4:
2587ec681f3Smrg    case D3DFMT_D16:
2597ec681f3Smrg    case D3DFMT_D24FS8:
2607ec681f3Smrg        return PIPE_BIND_DEPTH_STENCIL;
2617ec681f3Smrg    case D3DFMT_D32F_LOCKABLE:
2627ec681f3Smrg    case D3DFMT_D16_LOCKABLE:
2637ec681f3Smrg    case D3DFMT_D32_LOCKABLE:
2647ec681f3Smrg        return PIPE_BIND_DEPTH_STENCIL;
2657ec681f3Smrg    case D3DFMT_DF16:
2667ec681f3Smrg    case D3DFMT_DF24:
2677ec681f3Smrg    case D3DFMT_INTZ:
2687ec681f3Smrg        return PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_SAMPLER_VIEW;
2697ec681f3Smrg    default: unreachable("Unexpected format");
2707ec681f3Smrg    }
2717ec681f3Smrg}
2727ec681f3Smrg
2737ec681f3Smrgstatic inline enum pipe_format
2747ec681f3Smrgd3d9_to_pipe_format_internal(D3DFORMAT format)
2757ec681f3Smrg{
2767ec681f3Smrg    if (format <= D3DFMT_A2B10G10R10_XR_BIAS)
2777ec681f3Smrg        return nine_d3d9_to_pipe_format_map[format];
2787ec681f3Smrg    switch (format) {
2797ec681f3Smrg    case D3DFMT_INTZ: return PIPE_FORMAT_S8_UINT_Z24_UNORM;
2807ec681f3Smrg    case D3DFMT_DF16: return PIPE_FORMAT_Z16_UNORM;
2817ec681f3Smrg    case D3DFMT_DF24: return PIPE_FORMAT_X8Z24_UNORM;
2827ec681f3Smrg    case D3DFMT_DXT1: return PIPE_FORMAT_DXT1_RGBA;
2837ec681f3Smrg    case D3DFMT_DXT2: return PIPE_FORMAT_DXT3_RGBA; /* XXX */
2847ec681f3Smrg    case D3DFMT_DXT3: return PIPE_FORMAT_DXT3_RGBA;
2857ec681f3Smrg    case D3DFMT_DXT4: return PIPE_FORMAT_DXT5_RGBA; /* XXX */
2867ec681f3Smrg    case D3DFMT_DXT5: return PIPE_FORMAT_DXT5_RGBA;
2877ec681f3Smrg    case D3DFMT_ATI1: return PIPE_FORMAT_RGTC1_UNORM;
2887ec681f3Smrg    case D3DFMT_ATI2: return PIPE_FORMAT_RGTC2_UNORM;
2897ec681f3Smrg    case D3DFMT_UYVY: return PIPE_FORMAT_UYVY;
2907ec681f3Smrg    case D3DFMT_YUY2: return PIPE_FORMAT_YUYV; /* XXX check */
2917ec681f3Smrg    case D3DFMT_NV12: return PIPE_FORMAT_NV12;
2927ec681f3Smrg    case D3DFMT_G8R8_G8B8: return PIPE_FORMAT_G8R8_G8B8_UNORM; /* XXX order ? */
2937ec681f3Smrg    case D3DFMT_R8G8_B8G8: return PIPE_FORMAT_R8G8_B8G8_UNORM; /* XXX order ? */
2947ec681f3Smrg    case D3DFMT_BINARYBUFFER: return PIPE_FORMAT_NONE; /* not a format */
2957ec681f3Smrg    case D3DFMT_MULTI2_ARGB8: return PIPE_FORMAT_NONE; /* not supported */
2967ec681f3Smrg    case D3DFMT_Y210: /* XXX */
2977ec681f3Smrg    case D3DFMT_Y216:
2987ec681f3Smrg    case D3DFMT_NV11:
2997ec681f3Smrg    case D3DFMT_NULL: /* special cased, only for surfaces */
3007ec681f3Smrg        return PIPE_FORMAT_NONE;
3017ec681f3Smrg    default:
3027ec681f3Smrg        DBG_FLAG(DBG_UNKNOWN, "unknown D3DFORMAT: 0x%x/%c%c%c%c\n",
3037ec681f3Smrg                 format, (char)format, (char)(format >> 8),
3047ec681f3Smrg                 (char)(format >> 16), (char)(format >> 24));
3057ec681f3Smrg        return PIPE_FORMAT_NONE;
3067ec681f3Smrg    }
3077ec681f3Smrg}
3087ec681f3Smrg
3097ec681f3Smrg#define format_check_internal(pipe_format) \
3107ec681f3Smrg    screen->is_format_supported(screen, pipe_format, target, \
3117ec681f3Smrg                                sample_count, sample_count, bindings)
3127ec681f3Smrg
3137ec681f3Smrgstatic inline enum pipe_format
3147ec681f3Smrgd3d9_to_pipe_format_checked(struct pipe_screen *screen,
3157ec681f3Smrg                            D3DFORMAT format,
3167ec681f3Smrg                            enum pipe_texture_target target,
3177ec681f3Smrg                            unsigned sample_count,
3187ec681f3Smrg                            unsigned bindings,
3197ec681f3Smrg                            boolean srgb,
3207ec681f3Smrg                            boolean bypass_check)
3217ec681f3Smrg{
3227ec681f3Smrg    enum pipe_format result;
3237ec681f3Smrg
3247ec681f3Smrg    /* We cannot render to depth textures as a render target */
3257ec681f3Smrg    if (depth_stencil_format(format) && (bindings & PIPE_BIND_RENDER_TARGET))
3267ec681f3Smrg        return PIPE_FORMAT_NONE;
3277ec681f3Smrg
3287ec681f3Smrg    result = d3d9_to_pipe_format_internal(format);
3297ec681f3Smrg    if (result == PIPE_FORMAT_NONE)
3307ec681f3Smrg        return PIPE_FORMAT_NONE;
3317ec681f3Smrg
3327ec681f3Smrg    if (srgb)
3337ec681f3Smrg        result = util_format_srgb(result);
3347ec681f3Smrg
3357ec681f3Smrg    /* bypass_check: Used for D3DPOOL_SCRATCH, which
3367ec681f3Smrg     * isn't limited to the formats supported by the
3377ec681f3Smrg     * device, and to check we are not using a format
3387ec681f3Smrg     * fallback. */
3397ec681f3Smrg    if (bypass_check || format_check_internal(result))
3407ec681f3Smrg        return result;
3417ec681f3Smrg
3427ec681f3Smrg    /* fallback to another format for formats
3437ec681f3Smrg     * that match several pipe_format */
3447ec681f3Smrg    switch(format) {
3457ec681f3Smrg        /* depth buffer formats are not lockable (except those for which it
3467ec681f3Smrg         * is precised in the name), so it is ok to match to another similar
3477ec681f3Smrg         * format. In all cases, if the app reads the texture with a shader,
3487ec681f3Smrg         * it gets depth on r and doesn't get stencil.*/
3497ec681f3Smrg        case D3DFMT_INTZ:
3507ec681f3Smrg        case D3DFMT_D24S8:
3517ec681f3Smrg            if (format_check_internal(PIPE_FORMAT_Z24_UNORM_S8_UINT))
3527ec681f3Smrg                return PIPE_FORMAT_Z24_UNORM_S8_UINT;
3537ec681f3Smrg            break;
3547ec681f3Smrg        case D3DFMT_DF24:
3557ec681f3Smrg        case D3DFMT_D24X8:
3567ec681f3Smrg            if (format_check_internal(PIPE_FORMAT_Z24X8_UNORM))
3577ec681f3Smrg                return PIPE_FORMAT_Z24X8_UNORM;
3587ec681f3Smrg            break;
3597ec681f3Smrg        /* Support for X8L8V8U8 bumpenvmap format with lighting bits.
3607ec681f3Smrg         * X8L8V8U8 is commonly supported among dx9 cards.
3617ec681f3Smrg         * To avoid precision loss, we use PIPE_FORMAT_R32G32B32X32_FLOAT,
3627ec681f3Smrg         * however using PIPE_FORMAT_R8G8B8A8_SNORM should be ok */
3637ec681f3Smrg        case D3DFMT_X8L8V8U8:
3647ec681f3Smrg            if (bindings & PIPE_BIND_RENDER_TARGET)
3657ec681f3Smrg                return PIPE_FORMAT_NONE;
3667ec681f3Smrg            if (format_check_internal(PIPE_FORMAT_R32G32B32X32_FLOAT))
3677ec681f3Smrg                return PIPE_FORMAT_R32G32B32X32_FLOAT;
3687ec681f3Smrg            break;
3697ec681f3Smrg        /* Fallback for YUV formats */
3707ec681f3Smrg        case D3DFMT_UYVY:
3717ec681f3Smrg        case D3DFMT_YUY2:
3727ec681f3Smrg        case D3DFMT_NV12:
3737ec681f3Smrg            if (bindings & PIPE_BIND_RENDER_TARGET)
3747ec681f3Smrg                return PIPE_FORMAT_NONE;
3757ec681f3Smrg            if (format_check_internal(PIPE_FORMAT_R8G8B8X8_UNORM))
3767ec681f3Smrg                return PIPE_FORMAT_R8G8B8X8_UNORM;
3777ec681f3Smrg        default:
3787ec681f3Smrg            break;
3797ec681f3Smrg    }
3807ec681f3Smrg    return PIPE_FORMAT_NONE;
3817ec681f3Smrg}
3827ec681f3Smrg
3837ec681f3Smrg/* The quality levels are vendor dependent, so we set our own.
3847ec681f3Smrg * Every quality level has its own sample count and sample
3857ec681f3Smrg * position matrix.
3867ec681f3Smrg * The exact mapping might differ from system to system but thats OK,
3877ec681f3Smrg * as there's no way to gather more information about quality levels
3887ec681f3Smrg * in D3D9.
3897ec681f3Smrg * In case of NONMASKABLE multisample map every quality-level
3907ec681f3Smrg * to a MASKABLE MultiSampleType:
3917ec681f3Smrg *  0: no MSAA
3927ec681f3Smrg *  1: 2x MSAA
3937ec681f3Smrg *  2: 4x MSAA
3947ec681f3Smrg *  ...
3957ec681f3Smrg *  If the requested quality level is not available to nearest
3967ec681f3Smrg *  matching quality level is used.
3977ec681f3Smrg *  If no multisample is available the function sets
3987ec681f3Smrg *  multisample to D3DMULTISAMPLE_NONE and returns zero.
3997ec681f3Smrg */
4007ec681f3Smrgstatic inline HRESULT
4017ec681f3Smrgd3dmultisample_type_check(struct pipe_screen *screen,
4027ec681f3Smrg                          D3DFORMAT format,
4037ec681f3Smrg                          D3DMULTISAMPLE_TYPE *multisample,
4047ec681f3Smrg                          DWORD multisamplequality,
4057ec681f3Smrg                          DWORD *levels)
4067ec681f3Smrg{
4077ec681f3Smrg    unsigned bind, i;
4087ec681f3Smrg
4097ec681f3Smrg    assert(multisample);
4107ec681f3Smrg
4117ec681f3Smrg    if (levels)
4127ec681f3Smrg        *levels = 1;
4137ec681f3Smrg
4147ec681f3Smrg    /* Ignores multisamplequality */
4157ec681f3Smrg    if (*multisample == D3DMULTISAMPLE_NONE)
4167ec681f3Smrg        return D3D_OK;
4177ec681f3Smrg
4187ec681f3Smrg    if (*multisample == D3DMULTISAMPLE_NONMASKABLE) {
4197ec681f3Smrg        if (depth_stencil_format(format))
4207ec681f3Smrg            bind = d3d9_get_pipe_depth_format_bindings(format);
4217ec681f3Smrg        else /* render-target */
4227ec681f3Smrg            bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
4237ec681f3Smrg
4247ec681f3Smrg        *multisample = 0;
4257ec681f3Smrg        for (i = D3DMULTISAMPLE_2_SAMPLES; i < D3DMULTISAMPLE_16_SAMPLES &&
4267ec681f3Smrg            multisamplequality; ++i) {
4277ec681f3Smrg            if (d3d9_to_pipe_format_checked(screen, format, PIPE_TEXTURE_2D,
4287ec681f3Smrg                    i, bind, FALSE, FALSE) != PIPE_FORMAT_NONE) {
4297ec681f3Smrg                multisamplequality--;
4307ec681f3Smrg                if (levels)
4317ec681f3Smrg                    (*levels)++;
4327ec681f3Smrg                *multisample = i;
4337ec681f3Smrg            }
4347ec681f3Smrg        }
4357ec681f3Smrg    }
4367ec681f3Smrg    /* Make sure to get an exact match */
4377ec681f3Smrg    if (multisamplequality)
4387ec681f3Smrg        return D3DERR_INVALIDCALL;
4397ec681f3Smrg    return D3D_OK;
4407ec681f3Smrg}
4417ec681f3Smrg
4427ec681f3Smrgstatic inline const char *
4437ec681f3Smrgd3dformat_to_string(D3DFORMAT fmt)
4447ec681f3Smrg{
4457ec681f3Smrg    switch (fmt) {
4467ec681f3Smrg    case D3DFMT_UNKNOWN: return "D3DFMT_UNKNOWN";
4477ec681f3Smrg    case D3DFMT_R8G8B8: return "D3DFMT_R8G8B8";
4487ec681f3Smrg    case D3DFMT_A8R8G8B8: return "D3DFMT_A8R8G8B8";
4497ec681f3Smrg    case D3DFMT_X8R8G8B8: return "D3DFMT_X8R8G8B8";
4507ec681f3Smrg    case D3DFMT_R5G6B5: return "D3DFMT_R5G6B5";
4517ec681f3Smrg    case D3DFMT_X1R5G5B5: return "D3DFMT_X1R5G5B5";
4527ec681f3Smrg    case D3DFMT_A1R5G5B5: return "D3DFMT_A1R5G5B5";
4537ec681f3Smrg    case D3DFMT_A4R4G4B4: return "D3DFMT_A4R4G4B4";
4547ec681f3Smrg    case D3DFMT_R3G3B2: return "D3DFMT_R3G3B2";
4557ec681f3Smrg    case D3DFMT_A8: return "D3DFMT_A8";
4567ec681f3Smrg    case D3DFMT_A8R3G3B2: return "D3DFMT_A8R3G3B2";
4577ec681f3Smrg    case D3DFMT_X4R4G4B4: return "D3DFMT_X4R4G4B4";
4587ec681f3Smrg    case D3DFMT_A2B10G10R10: return "D3DFMT_A2B10G10R10";
4597ec681f3Smrg    case D3DFMT_A8B8G8R8: return "D3DFMT_A8B8G8R8";
4607ec681f3Smrg    case D3DFMT_X8B8G8R8: return "D3DFMT_X8B8G8R8";
4617ec681f3Smrg    case D3DFMT_G16R16: return "D3DFMT_G16R16";
4627ec681f3Smrg    case D3DFMT_A2R10G10B10: return "D3DFMT_A2R10G10B10";
4637ec681f3Smrg    case D3DFMT_A16B16G16R16: return "D3DFMT_A16B16G16R16";
4647ec681f3Smrg    case D3DFMT_A8P8: return "D3DFMT_A8P8";
4657ec681f3Smrg    case D3DFMT_P8: return "D3DFMT_P8";
4667ec681f3Smrg    case D3DFMT_L8: return "D3DFMT_L8";
4677ec681f3Smrg    case D3DFMT_A8L8: return "D3DFMT_A8L8";
4687ec681f3Smrg    case D3DFMT_A4L4: return "D3DFMT_A4L4";
4697ec681f3Smrg    case D3DFMT_V8U8: return "D3DFMT_V8U8";
4707ec681f3Smrg    case D3DFMT_L6V5U5: return "D3DFMT_L6V5U5";
4717ec681f3Smrg    case D3DFMT_X8L8V8U8: return "D3DFMT_X8L8V8U8";
4727ec681f3Smrg    case D3DFMT_Q8W8V8U8: return "D3DFMT_Q8W8V8U8";
4737ec681f3Smrg    case D3DFMT_V16U16: return "D3DFMT_V16U16";
4747ec681f3Smrg    case D3DFMT_A2W10V10U10: return "D3DFMT_A2W10V10U10";
4757ec681f3Smrg    case D3DFMT_UYVY: return "D3DFMT_UYVY";
4767ec681f3Smrg    case D3DFMT_R8G8_B8G8: return "D3DFMT_R8G8_B8G8";
4777ec681f3Smrg    case D3DFMT_YUY2: return "D3DFMT_YUY2";
4787ec681f3Smrg    case D3DFMT_G8R8_G8B8: return "D3DFMT_G8R8_G8B8";
4797ec681f3Smrg    case D3DFMT_DXT1: return "D3DFMT_DXT1";
4807ec681f3Smrg    case D3DFMT_DXT2: return "D3DFMT_DXT2";
4817ec681f3Smrg    case D3DFMT_DXT3: return "D3DFMT_DXT3";
4827ec681f3Smrg    case D3DFMT_DXT4: return "D3DFMT_DXT4";
4837ec681f3Smrg    case D3DFMT_DXT5: return "D3DFMT_DXT5";
4847ec681f3Smrg    case D3DFMT_ATI1: return "D3DFMT_ATI1";
4857ec681f3Smrg    case D3DFMT_ATI2: return "D3DFMT_ATI2";
4867ec681f3Smrg    case D3DFMT_D16_LOCKABLE: return "D3DFMT_D16_LOCKABLE";
4877ec681f3Smrg    case D3DFMT_D32: return "D3DFMT_D32";
4887ec681f3Smrg    case D3DFMT_D15S1: return "D3DFMT_D15S1";
4897ec681f3Smrg    case D3DFMT_D24S8: return "D3DFMT_D24S8";
4907ec681f3Smrg    case D3DFMT_D24X8: return "D3DFMT_D24X8";
4917ec681f3Smrg    case D3DFMT_D24X4S4: return "D3DFMT_D24X4S4";
4927ec681f3Smrg    case D3DFMT_D16: return "D3DFMT_D16";
4937ec681f3Smrg    case D3DFMT_D32F_LOCKABLE: return "D3DFMT_D32F_LOCKABLE";
4947ec681f3Smrg    case D3DFMT_D24FS8: return "D3DFMT_D24FS8";
4957ec681f3Smrg    case D3DFMT_D32_LOCKABLE: return "D3DFMT_D32_LOCKABLE";
4967ec681f3Smrg    case D3DFMT_S8_LOCKABLE: return "D3DFMT_S8_LOCKABLE";
4977ec681f3Smrg    case D3DFMT_L16: return "D3DFMT_L16";
4987ec681f3Smrg    case D3DFMT_VERTEXDATA: return "D3DFMT_VERTEXDATA";
4997ec681f3Smrg    case D3DFMT_INDEX16: return "D3DFMT_INDEX16";
5007ec681f3Smrg    case D3DFMT_INDEX32: return "D3DFMT_INDEX32";
5017ec681f3Smrg    case D3DFMT_Q16W16V16U16: return "D3DFMT_Q16W16V16U16";
5027ec681f3Smrg    case D3DFMT_MULTI2_ARGB8: return "D3DFMT_MULTI2_ARGB8";
5037ec681f3Smrg    case D3DFMT_R16F: return "D3DFMT_R16F";
5047ec681f3Smrg    case D3DFMT_G16R16F: return "D3DFMT_G16R16F";
5057ec681f3Smrg    case D3DFMT_A16B16G16R16F: return "D3DFMT_A16B16G16R16F";
5067ec681f3Smrg    case D3DFMT_R32F: return "D3DFMT_R32F";
5077ec681f3Smrg    case D3DFMT_G32R32F: return "D3DFMT_G32R32F";
5087ec681f3Smrg    case D3DFMT_A32B32G32R32F: return "D3DFMT_A32B32G32R32F";
5097ec681f3Smrg    case D3DFMT_CxV8U8: return "D3DFMT_CxV8U8";
5107ec681f3Smrg    case D3DFMT_A1: return "D3DFMT_A1";
5117ec681f3Smrg    case D3DFMT_A2B10G10R10_XR_BIAS: return "D3DFMT_A2B10G10R10_XR_BIAS";
5127ec681f3Smrg    case D3DFMT_BINARYBUFFER: return "D3DFMT_BINARYBUFFER";
5137ec681f3Smrg    case D3DFMT_DF16: return "D3DFMT_DF16";
5147ec681f3Smrg    case D3DFMT_DF24: return "D3DFMT_DF24";
5157ec681f3Smrg    case D3DFMT_INTZ: return "D3DFMT_INTZ";
5167ec681f3Smrg    case D3DFMT_NVDB: return "D3DFMT_NVDB";
5177ec681f3Smrg    case D3DFMT_RESZ: return "D3DFMT_RESZ";
5187ec681f3Smrg    case D3DFMT_NULL: return "D3DFMT_NULL";
5197ec681f3Smrg    case D3DFMT_ATOC: return "D3DFMT_ATOC";
5207ec681f3Smrg    default:
5217ec681f3Smrg        break;
5227ec681f3Smrg    }
5237ec681f3Smrg    return "Unknown";
5247ec681f3Smrg}
5257ec681f3Smrg
5267ec681f3Smrgstatic inline unsigned
5277ec681f3Smrgnine_fvf_stride( DWORD fvf )
5287ec681f3Smrg{
5297ec681f3Smrg    unsigned texcount, i, size = 0;
5307ec681f3Smrg
5317ec681f3Smrg    switch (fvf & D3DFVF_POSITION_MASK) {
5327ec681f3Smrg    case D3DFVF_XYZ:    size += 3*4; break;
5337ec681f3Smrg    case D3DFVF_XYZRHW: size += 4*4; break;
5347ec681f3Smrg    case D3DFVF_XYZB1:  size += 4*4; break;
5357ec681f3Smrg    case D3DFVF_XYZB2:  size += 5*4; break;
5367ec681f3Smrg    case D3DFVF_XYZB3:  size += 6*4; break;
5377ec681f3Smrg    case D3DFVF_XYZB4:  size += 7*4; break;
5387ec681f3Smrg    case D3DFVF_XYZB5:  size += 8*4; break;
5397ec681f3Smrg    case D3DFVF_XYZW:   size += 4*4; break;
5407ec681f3Smrg    default:
5417ec681f3Smrg        user_warn("Position doesn't match any known combination.");
5427ec681f3Smrg        break;
5437ec681f3Smrg    }
5447ec681f3Smrg
5457ec681f3Smrg    if (fvf & D3DFVF_NORMAL)   { size += 3*4; }
5467ec681f3Smrg    if (fvf & D3DFVF_PSIZE)    { size += 1*4; }
5477ec681f3Smrg    if (fvf & D3DFVF_DIFFUSE)  { size += 1*4; }
5487ec681f3Smrg    if (fvf & D3DFVF_SPECULAR) { size += 1*4; }
5497ec681f3Smrg
5507ec681f3Smrg    texcount = (fvf >> D3DFVF_TEXCOUNT_SHIFT) & D3DFVF_TEXCOUNT_MASK;
5517ec681f3Smrg    if (user_error(texcount <= 8))
5527ec681f3Smrg        texcount = 8;
5537ec681f3Smrg
5547ec681f3Smrg    for (i = 0; i < texcount; ++i) {
5557ec681f3Smrg        unsigned texformat = (fvf>>(16+i*2))&0x3;
5567ec681f3Smrg        /* texformats are defined having been shifted around so 1=3,2=0,3=1,4=2
5577ec681f3Smrg         * meaning we can just do this instead of the switch below */
5587ec681f3Smrg        size += (((texformat+1)&0x3)+1)*4;
5597ec681f3Smrg
5607ec681f3Smrg        /*
5617ec681f3Smrg        switch (texformat) {
5627ec681f3Smrg        case D3DFVF_TEXTUREFORMAT1: size += 1*4;
5637ec681f3Smrg        case D3DFVF_TEXTUREFORMAT2: size += 2*4;
5647ec681f3Smrg        case D3DFVF_TEXTUREFORMAT3: size += 3*4;
5657ec681f3Smrg        case D3DFVF_TEXTUREFORMAT4: size += 4*4;
5667ec681f3Smrg        }
5677ec681f3Smrg        */
5687ec681f3Smrg    }
5697ec681f3Smrg
5707ec681f3Smrg    return size;
5717ec681f3Smrg}
5727ec681f3Smrg
5737ec681f3Smrgstatic inline void
5747ec681f3Smrgd3dcolor_to_rgba(float *rgba, D3DCOLOR color)
5757ec681f3Smrg{
5767ec681f3Smrg    rgba[0] = (float)((color >> 16) & 0xFF) / 0xFF;
5777ec681f3Smrg    rgba[1] = (float)((color >>  8) & 0xFF) / 0xFF;
5787ec681f3Smrg    rgba[2] = (float)((color >>  0) & 0xFF) / 0xFF;
5797ec681f3Smrg    rgba[3] = (float)((color >> 24) & 0xFF) / 0xFF;
5807ec681f3Smrg}
5817ec681f3Smrg
5827ec681f3Smrgstatic inline void
5837ec681f3Smrgd3dcolor_to_pipe_color_union(union pipe_color_union *rgba, D3DCOLOR color)
5847ec681f3Smrg{
5857ec681f3Smrg    d3dcolor_to_rgba(&rgba->f[0], color);
5867ec681f3Smrg}
5877ec681f3Smrg
5887ec681f3Smrgstatic inline unsigned
5897ec681f3Smrgd3dprimitivetype_to_pipe_prim(D3DPRIMITIVETYPE prim)
5907ec681f3Smrg{
5917ec681f3Smrg    switch (prim) {
5927ec681f3Smrg    case D3DPT_POINTLIST:     return PIPE_PRIM_POINTS;
5937ec681f3Smrg    case D3DPT_LINELIST:      return PIPE_PRIM_LINES;
5947ec681f3Smrg    case D3DPT_LINESTRIP:     return PIPE_PRIM_LINE_STRIP;
5957ec681f3Smrg    case D3DPT_TRIANGLELIST:  return PIPE_PRIM_TRIANGLES;
5967ec681f3Smrg    case D3DPT_TRIANGLESTRIP: return PIPE_PRIM_TRIANGLE_STRIP;
5977ec681f3Smrg    case D3DPT_TRIANGLEFAN:   return PIPE_PRIM_TRIANGLE_FAN;
5987ec681f3Smrg    default:
5997ec681f3Smrg        assert(0);
6007ec681f3Smrg        return PIPE_PRIM_POINTS;
6017ec681f3Smrg    }
6027ec681f3Smrg}
6037ec681f3Smrg
6047ec681f3Smrgstatic inline unsigned
6057ec681f3Smrgprim_count_to_vertex_count(D3DPRIMITIVETYPE prim, UINT count)
6067ec681f3Smrg{
6077ec681f3Smrg    switch (prim) {
6087ec681f3Smrg    case D3DPT_POINTLIST:     return count;
6097ec681f3Smrg    case D3DPT_LINELIST:      return count * 2;
6107ec681f3Smrg    case D3DPT_LINESTRIP:     return count + 1;
6117ec681f3Smrg    case D3DPT_TRIANGLELIST:  return count * 3;
6127ec681f3Smrg    case D3DPT_TRIANGLESTRIP: return count + 2;
6137ec681f3Smrg    case D3DPT_TRIANGLEFAN:   return count + 2;
6147ec681f3Smrg    default:
6157ec681f3Smrg        assert(0);
6167ec681f3Smrg        return 0;
6177ec681f3Smrg    }
6187ec681f3Smrg}
6197ec681f3Smrg
6207ec681f3Smrgstatic inline unsigned
6217ec681f3Smrgd3dcmpfunc_to_pipe_func(D3DCMPFUNC func)
6227ec681f3Smrg{
6237ec681f3Smrg    switch (func) {
6247ec681f3Smrg    case D3DCMP_NEVER:        return PIPE_FUNC_NEVER;
6257ec681f3Smrg    case D3DCMP_LESS:         return PIPE_FUNC_LESS;
6267ec681f3Smrg    case D3DCMP_EQUAL:        return PIPE_FUNC_EQUAL;
6277ec681f3Smrg    case D3DCMP_LESSEQUAL:    return PIPE_FUNC_LEQUAL;
6287ec681f3Smrg    case D3DCMP_GREATER:      return PIPE_FUNC_GREATER;
6297ec681f3Smrg    case D3DCMP_NOTEQUAL:     return PIPE_FUNC_NOTEQUAL;
6307ec681f3Smrg    case D3DCMP_GREATEREQUAL: return PIPE_FUNC_GEQUAL;
6317ec681f3Smrg    case D3DCMP_ALWAYS:       return PIPE_FUNC_ALWAYS;
6327ec681f3Smrg    case D3DCMP_NEVER_ZERO:   return PIPE_FUNC_NEVER; // Tested on windows + ATI HD5770
6337ec681f3Smrg    default:
6347ec681f3Smrg        assert(0);
6357ec681f3Smrg        return PIPE_FUNC_NEVER;
6367ec681f3Smrg    }
6377ec681f3Smrg}
6387ec681f3Smrg
6397ec681f3Smrgstatic inline unsigned
6407ec681f3Smrgd3dstencilop_to_pipe_stencil_op(D3DSTENCILOP op)
6417ec681f3Smrg{
6427ec681f3Smrg    switch (op) {
6437ec681f3Smrg    case D3DSTENCILOP_KEEP:    return PIPE_STENCIL_OP_KEEP;
6447ec681f3Smrg    case D3DSTENCILOP_ZERO:    return PIPE_STENCIL_OP_ZERO;
6457ec681f3Smrg    case D3DSTENCILOP_REPLACE: return PIPE_STENCIL_OP_REPLACE;
6467ec681f3Smrg    case D3DSTENCILOP_INCRSAT: return PIPE_STENCIL_OP_INCR;
6477ec681f3Smrg    case D3DSTENCILOP_DECRSAT: return PIPE_STENCIL_OP_DECR;
6487ec681f3Smrg    case D3DSTENCILOP_INVERT:  return PIPE_STENCIL_OP_INVERT;
6497ec681f3Smrg    case D3DSTENCILOP_INCR:    return PIPE_STENCIL_OP_INCR_WRAP;
6507ec681f3Smrg    case D3DSTENCILOP_DECR:    return PIPE_STENCIL_OP_DECR_WRAP;
6517ec681f3Smrg    default:
6527ec681f3Smrg        return PIPE_STENCIL_OP_ZERO;
6537ec681f3Smrg    }
6547ec681f3Smrg}
6557ec681f3Smrg
6567ec681f3Smrgstatic inline unsigned
6577ec681f3Smrgd3dcull_to_pipe_face(D3DCULL cull)
6587ec681f3Smrg{
6597ec681f3Smrg    switch (cull) {
6607ec681f3Smrg    case D3DCULL_NONE: return PIPE_FACE_NONE;
6617ec681f3Smrg    case D3DCULL_CW:   return PIPE_FACE_FRONT;
6627ec681f3Smrg    case D3DCULL_CCW:  return PIPE_FACE_BACK;
6637ec681f3Smrg    default:
6647ec681f3Smrg        assert(0);
6657ec681f3Smrg        return PIPE_FACE_NONE;
6667ec681f3Smrg    }
6677ec681f3Smrg}
6687ec681f3Smrg
6697ec681f3Smrgstatic inline unsigned
6707ec681f3Smrgd3dfillmode_to_pipe_polygon_mode(D3DFILLMODE mode)
6717ec681f3Smrg{
6727ec681f3Smrg    switch (mode) {
6737ec681f3Smrg    case D3DFILL_POINT:     return PIPE_POLYGON_MODE_POINT;
6747ec681f3Smrg    case D3DFILL_WIREFRAME: return PIPE_POLYGON_MODE_LINE;
6757ec681f3Smrg    case D3DFILL_SOLID:     return PIPE_POLYGON_MODE_FILL;
6767ec681f3Smrg    case D3DFILL_SOLID_ZERO:return PIPE_POLYGON_MODE_FILL;
6777ec681f3Smrg    default:
6787ec681f3Smrg        assert(0);
6797ec681f3Smrg        return PIPE_POLYGON_MODE_FILL;
6807ec681f3Smrg    }
6817ec681f3Smrg}
6827ec681f3Smrg
6837ec681f3Smrgstatic inline unsigned
6847ec681f3Smrgd3dblendop_to_pipe_blend(D3DBLENDOP op)
6857ec681f3Smrg{
6867ec681f3Smrg    switch (op) {
6877ec681f3Smrg    case D3DBLENDOP_ADD:         return PIPE_BLEND_ADD;
6887ec681f3Smrg    case D3DBLENDOP_SUBTRACT:    return PIPE_BLEND_SUBTRACT;
6897ec681f3Smrg    case D3DBLENDOP_REVSUBTRACT: return PIPE_BLEND_REVERSE_SUBTRACT;
6907ec681f3Smrg    case D3DBLENDOP_MIN:         return PIPE_BLEND_MIN;
6917ec681f3Smrg    case D3DBLENDOP_MAX:         return PIPE_BLEND_MAX;
6927ec681f3Smrg    default:
6937ec681f3Smrg        assert(0);
6947ec681f3Smrg        return PIPE_BLEND_ADD;
6957ec681f3Smrg    }
6967ec681f3Smrg}
6977ec681f3Smrg
6987ec681f3Smrg/* NOTE: The COLOR factors for are equal to the ALPHA ones for alpha.
6997ec681f3Smrg * Drivers may check RGB and ALPHA factors for equality so we should not
7007ec681f3Smrg * simply substitute the ALPHA variants.
7017ec681f3Smrg */
7027ec681f3Smrgstatic inline unsigned
7037ec681f3Smrgd3dblend_alpha_to_pipe_blendfactor(D3DBLEND b)
7047ec681f3Smrg{
7057ec681f3Smrg    switch (b) {
7067ec681f3Smrg    case D3DBLEND_ZERO:            return PIPE_BLENDFACTOR_ZERO;
7077ec681f3Smrg    case D3DBLEND_ONE:             return PIPE_BLENDFACTOR_ONE;
7087ec681f3Smrg    case D3DBLEND_SRCCOLOR:        return PIPE_BLENDFACTOR_SRC_COLOR/*ALPHA*/;
7097ec681f3Smrg    case D3DBLEND_INVSRCCOLOR:     return PIPE_BLENDFACTOR_INV_SRC_COLOR/*ALPHA*/;
7107ec681f3Smrg    case D3DBLEND_SRCALPHA:        return PIPE_BLENDFACTOR_SRC_ALPHA;
7117ec681f3Smrg    case D3DBLEND_INVSRCALPHA:     return PIPE_BLENDFACTOR_INV_SRC_ALPHA;
7127ec681f3Smrg    case D3DBLEND_DESTALPHA:       return PIPE_BLENDFACTOR_DST_ALPHA;
7137ec681f3Smrg    case D3DBLEND_INVDESTALPHA:    return PIPE_BLENDFACTOR_INV_DST_ALPHA;
7147ec681f3Smrg    case D3DBLEND_DESTCOLOR:       return PIPE_BLENDFACTOR_DST_COLOR/*ALPHA*/;
7157ec681f3Smrg    case D3DBLEND_INVDESTCOLOR:    return PIPE_BLENDFACTOR_INV_DST_COLOR/*ALPHA*/;
7167ec681f3Smrg    case D3DBLEND_SRCALPHASAT:     return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE;
7177ec681f3Smrg    case D3DBLEND_BOTHSRCALPHA:    return PIPE_BLENDFACTOR_SRC_ALPHA;
7187ec681f3Smrg    case D3DBLEND_BOTHINVSRCALPHA: return PIPE_BLENDFACTOR_INV_SRC_ALPHA;
7197ec681f3Smrg    case D3DBLEND_BLENDFACTOR:     return PIPE_BLENDFACTOR_CONST_COLOR/*ALPHA*/;
7207ec681f3Smrg    case D3DBLEND_INVBLENDFACTOR:  return PIPE_BLENDFACTOR_INV_CONST_COLOR/*ALPHA*/;
7217ec681f3Smrg    case D3DBLEND_SRCCOLOR2:       return PIPE_BLENDFACTOR_ONE; /* XXX */
7227ec681f3Smrg    case D3DBLEND_INVSRCCOLOR2:    return PIPE_BLENDFACTOR_ZERO; /* XXX */
7237ec681f3Smrg    default:
7247ec681f3Smrg       DBG_FLAG(DBG_UNKNOWN, "Unhandled blend factor %d\n", b);
7257ec681f3Smrg       return PIPE_BLENDFACTOR_ZERO;
7267ec681f3Smrg    }
7277ec681f3Smrg}
7287ec681f3Smrg
7297ec681f3Smrgstatic inline unsigned
7307ec681f3Smrgd3dblend_color_to_pipe_blendfactor(D3DBLEND b)
7317ec681f3Smrg{
7327ec681f3Smrg    switch (b) {
7337ec681f3Smrg    case D3DBLEND_ZERO:            return PIPE_BLENDFACTOR_ZERO;
7347ec681f3Smrg    case D3DBLEND_ONE:             return PIPE_BLENDFACTOR_ONE;
7357ec681f3Smrg    case D3DBLEND_SRCCOLOR:        return PIPE_BLENDFACTOR_SRC_COLOR;
7367ec681f3Smrg    case D3DBLEND_INVSRCCOLOR:     return PIPE_BLENDFACTOR_INV_SRC_COLOR;
7377ec681f3Smrg    case D3DBLEND_SRCALPHA:        return PIPE_BLENDFACTOR_SRC_ALPHA;
7387ec681f3Smrg    case D3DBLEND_INVSRCALPHA:     return PIPE_BLENDFACTOR_INV_SRC_ALPHA;
7397ec681f3Smrg    case D3DBLEND_DESTALPHA:       return PIPE_BLENDFACTOR_DST_ALPHA;
7407ec681f3Smrg    case D3DBLEND_INVDESTALPHA:    return PIPE_BLENDFACTOR_INV_DST_ALPHA;
7417ec681f3Smrg    case D3DBLEND_DESTCOLOR:       return PIPE_BLENDFACTOR_DST_COLOR;
7427ec681f3Smrg    case D3DBLEND_INVDESTCOLOR:    return PIPE_BLENDFACTOR_INV_DST_COLOR;
7437ec681f3Smrg    case D3DBLEND_SRCALPHASAT:     return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE;
7447ec681f3Smrg    case D3DBLEND_BOTHSRCALPHA:    return PIPE_BLENDFACTOR_SRC_ALPHA;
7457ec681f3Smrg    case D3DBLEND_BOTHINVSRCALPHA: return PIPE_BLENDFACTOR_INV_SRC_ALPHA;
7467ec681f3Smrg    case D3DBLEND_BLENDFACTOR:     return PIPE_BLENDFACTOR_CONST_COLOR;
7477ec681f3Smrg    case D3DBLEND_INVBLENDFACTOR:  return PIPE_BLENDFACTOR_INV_CONST_COLOR;
7487ec681f3Smrg    case D3DBLEND_SRCCOLOR2:       return PIPE_BLENDFACTOR_SRC1_COLOR;
7497ec681f3Smrg    case D3DBLEND_INVSRCCOLOR2:    return PIPE_BLENDFACTOR_INV_SRC1_COLOR;
7507ec681f3Smrg    default:
7517ec681f3Smrg       DBG_FLAG(DBG_UNKNOWN, "Unhandled blend factor %d\n", b);
7527ec681f3Smrg       return PIPE_BLENDFACTOR_ZERO;
7537ec681f3Smrg    }
7547ec681f3Smrg}
7557ec681f3Smrg
7567ec681f3Smrgstatic inline unsigned
7577ec681f3Smrgd3dtextureaddress_to_pipe_tex_wrap(D3DTEXTUREADDRESS addr)
7587ec681f3Smrg{
7597ec681f3Smrg    switch (addr) {
7607ec681f3Smrg    case D3DTADDRESS_WRAP:       return PIPE_TEX_WRAP_REPEAT;
7617ec681f3Smrg    case D3DTADDRESS_MIRROR:     return PIPE_TEX_WRAP_MIRROR_REPEAT;
7627ec681f3Smrg    case D3DTADDRESS_CLAMP:      return PIPE_TEX_WRAP_CLAMP_TO_EDGE;
7637ec681f3Smrg    case D3DTADDRESS_BORDER:     return PIPE_TEX_WRAP_CLAMP_TO_BORDER;
7647ec681f3Smrg    case D3DTADDRESS_MIRRORONCE: return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE;
7657ec681f3Smrg    default:
7667ec681f3Smrg        assert(0);
7677ec681f3Smrg        return PIPE_TEX_WRAP_CLAMP_TO_EDGE;
7687ec681f3Smrg    }
7697ec681f3Smrg}
7707ec681f3Smrg
7717ec681f3Smrgstatic inline unsigned
7727ec681f3Smrgd3dtexturefiltertype_to_pipe_tex_filter(D3DTEXTUREFILTERTYPE filter)
7737ec681f3Smrg{
7747ec681f3Smrg    switch (filter) {
7757ec681f3Smrg    case D3DTEXF_POINT:       return PIPE_TEX_FILTER_NEAREST;
7767ec681f3Smrg    case D3DTEXF_LINEAR:      return PIPE_TEX_FILTER_LINEAR;
7777ec681f3Smrg    case D3DTEXF_ANISOTROPIC: return PIPE_TEX_FILTER_LINEAR;
7787ec681f3Smrg
7797ec681f3Smrg    case D3DTEXF_NONE:
7807ec681f3Smrg    case D3DTEXF_PYRAMIDALQUAD:
7817ec681f3Smrg    case D3DTEXF_GAUSSIANQUAD:
7827ec681f3Smrg    case D3DTEXF_CONVOLUTIONMONO:
7837ec681f3Smrg    default:
7847ec681f3Smrg        assert(0);
7857ec681f3Smrg        return PIPE_TEX_FILTER_NEAREST;
7867ec681f3Smrg    }
7877ec681f3Smrg}
7887ec681f3Smrg
7897ec681f3Smrgstatic inline unsigned
7907ec681f3Smrgd3dtexturefiltertype_to_pipe_tex_mipfilter(D3DTEXTUREFILTERTYPE filter)
7917ec681f3Smrg{
7927ec681f3Smrg    switch (filter) {
7937ec681f3Smrg    case D3DTEXF_NONE:        return PIPE_TEX_MIPFILTER_NONE;
7947ec681f3Smrg    case D3DTEXF_POINT:       return PIPE_TEX_FILTER_NEAREST;
7957ec681f3Smrg    case D3DTEXF_LINEAR:      return PIPE_TEX_FILTER_LINEAR;
7967ec681f3Smrg    case D3DTEXF_ANISOTROPIC: return PIPE_TEX_FILTER_LINEAR;
7977ec681f3Smrg
7987ec681f3Smrg    case D3DTEXF_PYRAMIDALQUAD:
7997ec681f3Smrg    case D3DTEXF_GAUSSIANQUAD:
8007ec681f3Smrg    case D3DTEXF_CONVOLUTIONMONO:
8017ec681f3Smrg    default:
8027ec681f3Smrg        assert(0);
8037ec681f3Smrg        return PIPE_TEX_MIPFILTER_NONE;
8047ec681f3Smrg    }
8057ec681f3Smrg}
8067ec681f3Smrg
8077ec681f3Smrgstatic inline unsigned nine_format_get_stride(enum pipe_format format,
8087ec681f3Smrg                                              unsigned width)
8097ec681f3Smrg{
8107ec681f3Smrg    unsigned stride = util_format_get_stride(format, width);
8117ec681f3Smrg
8127ec681f3Smrg    return align(stride, 4);
8137ec681f3Smrg}
8147ec681f3Smrg
8157ec681f3Smrgstatic inline unsigned nine_format_get_level_alloc_size(enum pipe_format format,
8167ec681f3Smrg                                                        unsigned width,
8177ec681f3Smrg                                                        unsigned height,
8187ec681f3Smrg                                                        unsigned level)
8197ec681f3Smrg{
8207ec681f3Smrg    unsigned w, h, size;
8217ec681f3Smrg
8227ec681f3Smrg    w = u_minify(width, level);
8237ec681f3Smrg    h = u_minify(height, level);
8247ec681f3Smrg    if (is_ATI1_ATI2(format)) {
8257ec681f3Smrg        /* For "unknown" formats like ATIx use width * height bytes */
8267ec681f3Smrg        size = w * h;
8277ec681f3Smrg    } else if (format == PIPE_FORMAT_NONE) { /* D3DFMT_NULL */
8287ec681f3Smrg        size = w * h * 4;
8297ec681f3Smrg    } else {
8307ec681f3Smrg        size = nine_format_get_stride(format, w) *
8317ec681f3Smrg            util_format_get_nblocksy(format, h);
8327ec681f3Smrg    }
8337ec681f3Smrg
8347ec681f3Smrg    return size;
8357ec681f3Smrg}
8367ec681f3Smrg
8377ec681f3Smrgstatic inline unsigned nine_format_get_size_and_offsets(enum pipe_format format,
8387ec681f3Smrg                                                        unsigned *offsets,
8397ec681f3Smrg                                                        unsigned width,
8407ec681f3Smrg                                                        unsigned height,
8417ec681f3Smrg                                                        unsigned last_level)
8427ec681f3Smrg{
8437ec681f3Smrg    unsigned l, w, h, size = 0;
8447ec681f3Smrg
8457ec681f3Smrg    for (l = 0; l <= last_level; ++l) {
8467ec681f3Smrg        w = u_minify(width, l);
8477ec681f3Smrg        h = u_minify(height, l);
8487ec681f3Smrg        offsets[l] = size;
8497ec681f3Smrg        if (is_ATI1_ATI2(format)) {
8507ec681f3Smrg            /* For "unknown" formats like ATIx use width * height bytes */
8517ec681f3Smrg            size += w * h;
8527ec681f3Smrg        } else {
8537ec681f3Smrg            size += nine_format_get_stride(format, w) *
8547ec681f3Smrg                util_format_get_nblocksy(format, h);
8557ec681f3Smrg        }
8567ec681f3Smrg    }
8577ec681f3Smrg
8587ec681f3Smrg    return size;
8597ec681f3Smrg}
8607ec681f3Smrg
8617ec681f3Smrg#endif /* _NINE_PIPE_H_ */
862