vmwgfx_xa_surface.c revision 22f7e8e5
13bfa90b6Smrg/* 23bfa90b6Smrg * Copyright 2011 VMWare, Inc. 33bfa90b6Smrg * All Rights Reserved. 43bfa90b6Smrg * 53bfa90b6Smrg * Permission is hereby granted, free of charge, to any person obtaining a 63bfa90b6Smrg * copy of this software and associated documentation files (the 73bfa90b6Smrg * "Software"), to deal in the Software without restriction, including 83bfa90b6Smrg * without limitation the rights to use, copy, modify, merge, publish, 93bfa90b6Smrg * distribute, sub license, and/or sell copies of the Software, and to 103bfa90b6Smrg * permit persons to whom the Software is furnished to do so, subject to 113bfa90b6Smrg * the following conditions: 123bfa90b6Smrg * 133bfa90b6Smrg * The above copyright notice and this permission notice (including the 143bfa90b6Smrg * next paragraph) shall be included in all copies or substantial portions 153bfa90b6Smrg * of the Software. 163bfa90b6Smrg * 173bfa90b6Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 183bfa90b6Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 193bfa90b6Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 203bfa90b6Smrg * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 213bfa90b6Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 223bfa90b6Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 233bfa90b6Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 243bfa90b6Smrg * 253bfa90b6Smrg * Author: Thomas Hellstrom <thellstrom@vmware.com> 263bfa90b6Smrg */ 273bfa90b6Smrg#ifdef _HAVE_CONFIG_H_ 283bfa90b6Smrg#include "config.h" 293bfa90b6Smrg#endif 303bfa90b6Smrg 313bfa90b6Smrg#include <xorg-server.h> 323bfa90b6Smrg#include "vmwgfx_saa_priv.h" 333bfa90b6Smrg 343bfa90b6Smrg 353bfa90b6Smrgstatic const enum xa_surface_type vmwgfx_stype_map[] = { 363bfa90b6Smrg [PICT_TYPE_OTHER] = xa_type_other, 373bfa90b6Smrg [PICT_TYPE_A] = xa_type_a, 383bfa90b6Smrg [PICT_TYPE_ARGB] = xa_type_argb, 393bfa90b6Smrg [PICT_TYPE_ABGR] = xa_type_abgr, 403bfa90b6Smrg [PICT_TYPE_BGRA] = xa_type_bgra 413bfa90b6Smrg}; 423bfa90b6Smrg 433bfa90b6Smrgstatic const unsigned int vmwgfx_stype_map_size = 443bfa90b6Smrg sizeof(vmwgfx_stype_map) / sizeof(enum xa_surface_type); 453bfa90b6Smrg 463bfa90b6Smrg 473bfa90b6Smrg/* 483bfa90b6Smrg * Create an xa format from a PICT format. 493bfa90b6Smrg */ 503bfa90b6Smrgenum xa_formats 513bfa90b6Smrgvmwgfx_xa_format(enum _PictFormatShort format) 523bfa90b6Smrg{ 533bfa90b6Smrg uint32_t ptype = PICT_FORMAT_TYPE(format); 543bfa90b6Smrg 553bfa90b6Smrg if (ptype >= vmwgfx_stype_map_size || 563bfa90b6Smrg vmwgfx_stype_map[ptype] == 0 || 573bfa90b6Smrg vmwgfx_stype_map[ptype] == xa_type_other) 583bfa90b6Smrg return xa_format_unknown; 593bfa90b6Smrg 603bfa90b6Smrg return xa_format(PICT_FORMAT_BPP(format), 613bfa90b6Smrg vmwgfx_stype_map[ptype], 623bfa90b6Smrg PICT_FORMAT_A(format), 633bfa90b6Smrg PICT_FORMAT_R(format), 643bfa90b6Smrg PICT_FORMAT_G(format), 653bfa90b6Smrg PICT_FORMAT_B(format)); 663bfa90b6Smrg} 673bfa90b6Smrg 683bfa90b6Smrg/* 693bfa90b6Smrg * Choose formats and flags for a dri2 surface. 703bfa90b6Smrg */ 713bfa90b6Smrgstatic Bool 723bfa90b6Smrgvmwgfx_hw_dri2_stage(PixmapPtr pixmap, unsigned int depth) 733bfa90b6Smrg{ 743bfa90b6Smrg struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); 753bfa90b6Smrg enum xa_formats format; 763bfa90b6Smrg 773bfa90b6Smrg if (depth == 0) 783bfa90b6Smrg depth = pixmap->drawable.depth; 793bfa90b6Smrg 803bfa90b6Smrg switch(depth) { 813bfa90b6Smrg case 32: 823bfa90b6Smrg format = xa_format_a8r8g8b8; 833bfa90b6Smrg break; 843bfa90b6Smrg case 24: 853bfa90b6Smrg format = xa_format_x8r8g8b8; 863bfa90b6Smrg break; 873bfa90b6Smrg case 16: 883bfa90b6Smrg format = xa_format_r5g6b5; 893bfa90b6Smrg break; 903bfa90b6Smrg case 15: 913bfa90b6Smrg format = xa_format_x1r5g5b5; 923bfa90b6Smrg break; 933bfa90b6Smrg default: 943bfa90b6Smrg return FALSE; 953bfa90b6Smrg } 963bfa90b6Smrg 973bfa90b6Smrg vpix->staging_format = format; 983bfa90b6Smrg vpix->staging_remove_flags = 0; 993bfa90b6Smrg vpix->staging_add_flags = XA_FLAG_RENDER_TARGET | XA_FLAG_SHARED; 1003bfa90b6Smrg 1013bfa90b6Smrg return TRUE; 1023bfa90b6Smrg} 1033bfa90b6Smrg 1043bfa90b6Smrg/* 1053bfa90b6Smrg * Is composite old format compatible? Only difference is that old format 1063bfa90b6Smrg * has more alpha bits? 1073bfa90b6Smrg */ 1083bfa90b6Smrgstatic inline Bool 1093bfa90b6Smrgvmwgfx_old_format_compatible(enum xa_formats format, 1103bfa90b6Smrg enum xa_formats old_format) 1113bfa90b6Smrg{ 1123bfa90b6Smrg return (format == old_format || 1133bfa90b6Smrg (xa_format_type(format) == xa_format_type(old_format) && 1143bfa90b6Smrg xa_format_a(format) <= xa_format_a(old_format) && 1153bfa90b6Smrg xa_format_r(format) == xa_format_r(old_format) && 1163bfa90b6Smrg xa_format_g(format) == xa_format_g(old_format) && 1173bfa90b6Smrg xa_format_b(format) == xa_format_b(old_format))); 1183bfa90b6Smrg} 1193bfa90b6Smrg 1203bfa90b6Smrg 1213bfa90b6Smrg/* 1223bfa90b6Smrg * Choose format and flags for a composite dst surface. 1233bfa90b6Smrg */ 1243bfa90b6SmrgBool 1253bfa90b6Smrgvmwgfx_hw_composite_dst_stage(PixmapPtr pixmap, 1263bfa90b6Smrg enum _PictFormatShort pict_format) 1273bfa90b6Smrg{ 1283bfa90b6Smrg struct vmwgfx_saa *vsaa = 1293bfa90b6Smrg to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen)); 1303bfa90b6Smrg struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); 1313bfa90b6Smrg enum xa_formats format = vmwgfx_xa_format(pict_format); 1323bfa90b6Smrg 1333bfa90b6Smrg /* 1343bfa90b6Smrg * Check if we can reuse old hardware format. 1353bfa90b6Smrg */ 1363bfa90b6Smrg if (vpix->hw) { 1373bfa90b6Smrg enum xa_formats old_format = xa_surface_format(vpix->hw); 1383bfa90b6Smrg 1393bfa90b6Smrg if (vmwgfx_old_format_compatible(format, old_format)) 1403bfa90b6Smrg format = old_format; 1413bfa90b6Smrg } 1423bfa90b6Smrg 1433bfa90b6Smrg if (xa_format_check_supported(vsaa->xat, format, 1443bfa90b6Smrg vpix->xa_flags | XA_FLAG_RENDER_TARGET) != 1453bfa90b6Smrg XA_ERR_NONE) { 1463bfa90b6Smrg return FALSE; 1473bfa90b6Smrg } 1483bfa90b6Smrg 1493bfa90b6Smrg vpix->staging_format = format; 1503bfa90b6Smrg vpix->staging_remove_flags = 0; 1513bfa90b6Smrg vpix->staging_add_flags = XA_FLAG_RENDER_TARGET | XA_FLAG_SHARED; 1523bfa90b6Smrg 1533bfa90b6Smrg return TRUE; 1543bfa90b6Smrg} 1553bfa90b6Smrg 1563bfa90b6Smrg/* 1573bfa90b6Smrg * Choose format and flags for a composite src surface. 1583bfa90b6Smrg */ 1593bfa90b6SmrgBool 1603bfa90b6Smrgvmwgfx_hw_composite_src_stage(PixmapPtr pixmap, 1613bfa90b6Smrg enum _PictFormatShort pict_format) 1623bfa90b6Smrg{ 1633bfa90b6Smrg struct vmwgfx_saa *vsaa = 1643bfa90b6Smrg to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen)); 1653bfa90b6Smrg struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); 1663bfa90b6Smrg enum xa_formats format = vmwgfx_xa_format(pict_format); 1673bfa90b6Smrg enum xa_formats swizzle_format = xa_format_unknown; 1683bfa90b6Smrg enum xa_surface_type ftype; 1693bfa90b6Smrg 1703bfa90b6Smrg if (format == xa_format_unknown) 1713bfa90b6Smrg return FALSE; 1723bfa90b6Smrg 1733bfa90b6Smrg ftype = xa_format_type(format); 1743bfa90b6Smrg if (ftype == xa_type_abgr) { 1753bfa90b6Smrg 1763bfa90b6Smrg swizzle_format = xa_format(xa_format_bpp(format), 1773bfa90b6Smrg xa_type_argb, 1783bfa90b6Smrg xa_format_a(format), 1793bfa90b6Smrg xa_format_r(format), 1803bfa90b6Smrg xa_format_g(format), 1813bfa90b6Smrg xa_format_b(format)); 1823bfa90b6Smrg } 1833bfa90b6Smrg 1843bfa90b6Smrg /* 1853bfa90b6Smrg * Check if we can reuse old format. 1863bfa90b6Smrg */ 1873bfa90b6Smrg 1883bfa90b6Smrg if (vpix->hw) { 1893bfa90b6Smrg enum xa_formats old_format = xa_surface_format(vpix->hw); 1903bfa90b6Smrg 1913bfa90b6Smrg if (vmwgfx_old_format_compatible(format, old_format) || 1923bfa90b6Smrg (swizzle_format != xa_format_unknown && 1933bfa90b6Smrg vmwgfx_old_format_compatible(swizzle_format, old_format))) { 1943bfa90b6Smrg format = old_format; 1953bfa90b6Smrg goto have_format; 1963bfa90b6Smrg } 1973bfa90b6Smrg } 1983bfa90b6Smrg 1993bfa90b6Smrg if (swizzle_format != xa_format_unknown && 2003bfa90b6Smrg xa_format_check_supported(vsaa->xat, swizzle_format, vpix->xa_flags) == 2013bfa90b6Smrg XA_ERR_NONE) { 2023bfa90b6Smrg format = swizzle_format; 2033bfa90b6Smrg goto have_format; 2043bfa90b6Smrg } 2053bfa90b6Smrg 2063bfa90b6Smrg if (xa_format_check_supported(vsaa->xat, format, vpix->xa_flags) == 2073bfa90b6Smrg XA_ERR_NONE) { 2083bfa90b6Smrg goto have_format; 2093bfa90b6Smrg } 2103bfa90b6Smrg 2113bfa90b6Smrg return FALSE; 2123bfa90b6Smrg have_format: 2133bfa90b6Smrg vpix->staging_format = format; 2143bfa90b6Smrg vpix->staging_remove_flags = 0; 2153bfa90b6Smrg vpix->staging_add_flags = 0; 2163bfa90b6Smrg 2173bfa90b6Smrg return TRUE; 2183bfa90b6Smrg} 2193bfa90b6Smrg 2203bfa90b6Smrg/* 2213bfa90b6Smrg * Choose accel format given depth. 2223bfa90b6Smrg */ 2233bfa90b6Smrgstatic enum xa_formats 2243bfa90b6Smrgvmwgfx_choose_accel_format(unsigned int depth) 2253bfa90b6Smrg{ 2263bfa90b6Smrg switch(depth) { 2273bfa90b6Smrg case 32: 2283bfa90b6Smrg return xa_format_a8r8g8b8; 2293bfa90b6Smrg case 24: 2303bfa90b6Smrg return xa_format_x8r8g8b8; 2313bfa90b6Smrg case 16: 2323bfa90b6Smrg return xa_format_r5g6b5; 2333bfa90b6Smrg case 15: 2343bfa90b6Smrg return xa_format_x1r5g5b5; 2353bfa90b6Smrg case 8: 2363bfa90b6Smrg return xa_format_a8; 2373bfa90b6Smrg default: 2383bfa90b6Smrg break; 2393bfa90b6Smrg } 2403bfa90b6Smrg return xa_format_unknown; 2413bfa90b6Smrg} 2423bfa90b6Smrg 2433bfa90b6Smrg 2443bfa90b6Smrg/* 2453bfa90b6Smrg * Determine xa format and flags for an ordinary accel surface. 2463bfa90b6Smrg */ 2473bfa90b6SmrgBool 2483bfa90b6Smrgvmwgfx_hw_accel_stage(PixmapPtr pixmap, unsigned int depth, 2493bfa90b6Smrg uint32_t add_flags, uint32_t remove_flags) 2503bfa90b6Smrg{ 2513bfa90b6Smrg struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); 2523bfa90b6Smrg enum xa_formats format = xa_format_unknown; 2533bfa90b6Smrg 2543bfa90b6Smrg if (depth == 0) 2553bfa90b6Smrg depth = pixmap->drawable.depth; 2563bfa90b6Smrg 2573bfa90b6Smrg if (vpix->hw) { 2583bfa90b6Smrg enum xa_formats old_format = xa_surface_format(vpix->hw); 2593bfa90b6Smrg enum xa_surface_type ftype = xa_format_type(old_format); 2603bfa90b6Smrg 2613bfa90b6Smrg if (ftype != xa_type_argb && 2623bfa90b6Smrg ftype != xa_type_a) { 2633bfa90b6Smrg LogMessage(X_ERROR, 2643bfa90b6Smrg "Acceleration fallback due to strange hw format.\n"); 2653bfa90b6Smrg return FALSE; 2663bfa90b6Smrg } 2673bfa90b6Smrg 2683bfa90b6Smrg if (xa_format_depth(old_format) == depth || 2693bfa90b6Smrg (xa_format_depth(old_format) == 32 && 2703bfa90b6Smrg depth == 24)) 2713bfa90b6Smrg format = old_format; 2723bfa90b6Smrg } 2733bfa90b6Smrg 2743bfa90b6Smrg if (format == xa_format_unknown) 2753bfa90b6Smrg format = vmwgfx_choose_accel_format(depth); 2763bfa90b6Smrg 2773bfa90b6Smrg if (format == xa_format_unknown) 2783bfa90b6Smrg return FALSE; 2793bfa90b6Smrg 2803bfa90b6Smrg vpix->staging_add_flags = add_flags; 2813bfa90b6Smrg vpix->staging_remove_flags = remove_flags; 2823bfa90b6Smrg vpix->staging_format = format; 2833bfa90b6Smrg 2843bfa90b6Smrg return TRUE; 2853bfa90b6Smrg} 2863bfa90b6Smrg 2873bfa90b6Smrg/* 2883bfa90b6Smrg * Create a surface with a format and flags determined by one of 2893bfa90b6Smrg * the staging functions. 2903bfa90b6Smrg */ 2913bfa90b6SmrgBool 2923bfa90b6Smrgvmwgfx_hw_commit(PixmapPtr pixmap) 2933bfa90b6Smrg{ 2943bfa90b6Smrg struct vmwgfx_saa *vsaa = 2953bfa90b6Smrg to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen)); 2963bfa90b6Smrg struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); 2973bfa90b6Smrg struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix); 2983bfa90b6Smrg enum xa_formats format = vpix->staging_format; 2993bfa90b6Smrg 3003bfa90b6Smrg if (vpix->hw) { 3013bfa90b6Smrg enum xa_formats old_format = xa_surface_format(vpix->hw); 3023bfa90b6Smrg 3033bfa90b6Smrg if (vpix->staging_format != old_format) { 3043bfa90b6Smrg if (xa_format_type(format) != xa_format_type(old_format) || 3053bfa90b6Smrg xa_format_r(format) != xa_format_r(old_format) || 3063bfa90b6Smrg xa_format_g(format) != xa_format_g(old_format) || 3073bfa90b6Smrg xa_format_b(format) != xa_format_b(old_format)) { 3083bfa90b6Smrg 3093bfa90b6Smrg LogMessage(X_INFO, "Killing old hw surface.\n"); 3103bfa90b6Smrg 3113bfa90b6Smrg if (!vmwgfx_hw_kill(vsaa, spix)) 3123bfa90b6Smrg return FALSE; 3133bfa90b6Smrg } 3143bfa90b6Smrg } 3153bfa90b6Smrg } 3163bfa90b6Smrg 3173bfa90b6Smrg if (vpix->hw) { 3183bfa90b6Smrg uint32_t new_flags; 3193bfa90b6Smrg 3203bfa90b6Smrg new_flags = (vpix->xa_flags & ~vpix->staging_remove_flags) | 32122f7e8e5Smrg vpix->staging_add_flags | XA_FLAG_SHARED; 3223bfa90b6Smrg 3233bfa90b6Smrg if (vpix->staging_format != xa_surface_format(vpix->hw)) 3243bfa90b6Smrg LogMessage(X_INFO, "Changing hardware format.\n"); 3253bfa90b6Smrg 3263bfa90b6Smrg if (xa_surface_redefine(vpix->hw, 3273bfa90b6Smrg pixmap->drawable.width, 3283bfa90b6Smrg pixmap->drawable.height, 3293bfa90b6Smrg 0, 3303bfa90b6Smrg xa_type_other, 3313bfa90b6Smrg vpix->staging_format, 3323bfa90b6Smrg new_flags, 1) != XA_ERR_NONE) 3333bfa90b6Smrg return FALSE; 3343bfa90b6Smrg vpix->xa_flags = new_flags; 3353bfa90b6Smrg } else if (!vmwgfx_create_hw(vsaa, pixmap)) 3363bfa90b6Smrg return FALSE; 3373bfa90b6Smrg 3383bfa90b6Smrg return TRUE; 3393bfa90b6Smrg} 3403bfa90b6Smrg 3413bfa90b6Smrg/* 3423bfa90b6Smrg * Create an accel surface if there is none, and make sure the region 3433bfa90b6Smrg * given by @region is valid. If @region is NULL, the whole surface 3443bfa90b6Smrg * will be valid. This is a utility convenience function only. 3453bfa90b6Smrg */ 3463bfa90b6SmrgBool 3473bfa90b6Smrgvmwgfx_hw_accel_validate(PixmapPtr pixmap, unsigned int depth, 3483bfa90b6Smrg uint32_t add_flags, uint32_t remove_flags, 3493bfa90b6Smrg RegionPtr region) 3503bfa90b6Smrg{ 3513bfa90b6Smrg return (vmwgfx_hw_accel_stage(pixmap, depth, add_flags, remove_flags) && 3523bfa90b6Smrg vmwgfx_hw_commit(pixmap) && 3533bfa90b6Smrg vmwgfx_hw_validate(pixmap, region)); 3543bfa90b6Smrg} 3553bfa90b6Smrg 3563bfa90b6Smrg 3573bfa90b6Smrg/* 3583bfa90b6Smrg * Create a dri2 surface if there is none, 3593bfa90b6Smrg * and make sure the whole surfade is valid. 3603bfa90b6Smrg * This is a utility convenience function only. 3613bfa90b6Smrg */ 3623bfa90b6SmrgBool 3633bfa90b6Smrgvmwgfx_hw_dri2_validate(PixmapPtr pixmap, unsigned int depth) 3643bfa90b6Smrg{ 36522f7e8e5Smrg struct vmwgfx_saa *vsaa = 36622f7e8e5Smrg to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen)); 36722f7e8e5Smrg 36822f7e8e5Smrg if (!vsaa->is_master) 36922f7e8e5Smrg return FALSE; 37022f7e8e5Smrg 3713bfa90b6Smrg return (vmwgfx_hw_dri2_stage(pixmap, depth) && 3723bfa90b6Smrg vmwgfx_hw_commit(pixmap) && 3733bfa90b6Smrg vmwgfx_hw_validate(pixmap, NULL)); 3743bfa90b6Smrg} 375