13bfa90b6Smrg/*
23bfa90b6Smrg * Copyright © 2009 Maarten Maathuis
33bfa90b6Smrg * Copyright 2011 VMWare, Inc. 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: Based on "exa_driver.c"
263bfa90b6Smrg * Author: Thomas Hellstrom <thellstrom@vmware.com>
273bfa90b6Smrg */
283bfa90b6Smrg
293bfa90b6Smrg#include "saa_priv.h"
303bfa90b6Smrg#include "saa.h"
313bfa90b6Smrg
323bfa90b6SmrgPixmapPtr
333bfa90b6Smrgsaa_create_pixmap(ScreenPtr pScreen, int w, int h, int depth,
343bfa90b6Smrg		  unsigned usage_hint)
353bfa90b6Smrg{
363bfa90b6Smrg    PixmapPtr pPixmap;
373bfa90b6Smrg    struct saa_pixmap *spix;
383bfa90b6Smrg    int bpp;
393bfa90b6Smrg    size_t paddedWidth;
403bfa90b6Smrg    struct saa_screen_priv *sscreen = saa_screen(pScreen);
413bfa90b6Smrg    int new_pitch = 0;
423bfa90b6Smrg    struct saa_driver *driver = sscreen->driver;
433bfa90b6Smrg
443bfa90b6Smrg    if (w > 32767 || h > 32767)
453bfa90b6Smrg	return NullPixmap;
463bfa90b6Smrg
473bfa90b6Smrg    /*
483bfa90b6Smrg     * Create a scratch pixmap without backing storage (w and h are zero)
493bfa90b6Smrg     */
503bfa90b6Smrg
513bfa90b6Smrg    saa_swap(sscreen, pScreen, CreatePixmap);
523bfa90b6Smrg    pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint);
533bfa90b6Smrg    saa_swap(sscreen, pScreen, CreatePixmap);
543bfa90b6Smrg
553bfa90b6Smrg    if (!pPixmap)
563bfa90b6Smrg	goto out_no_pix;
573bfa90b6Smrg
583bfa90b6Smrg    spix = saa_pixmap(pPixmap);
593bfa90b6Smrg    memset(spix, 0, driver->pixmap_size);
603bfa90b6Smrg    REGION_NULL(pScreen, &spix->dirty_shadow);
613bfa90b6Smrg    REGION_NULL(pScreen, &spix->dirty_hw);
623bfa90b6Smrg    REGION_NULL(pScreen, &spix->shadow_damage);
633bfa90b6Smrg    spix->read_access = 0;
643bfa90b6Smrg    spix->write_access = 0;
653bfa90b6Smrg    spix->mapped_access = 0;
663bfa90b6Smrg    spix->addr = NULL;
673bfa90b6Smrg    spix->auth_loc = saa_loc_override;
683bfa90b6Smrg    spix->override = SAA_INVALID_ADDRESS;
693bfa90b6Smrg    spix->pixmap = pPixmap;
703bfa90b6Smrg    bpp = pPixmap->drawable.bitsPerPixel;
713bfa90b6Smrg
723bfa90b6Smrg    if (!driver->create_pixmap(driver, spix, w, h, depth,
733bfa90b6Smrg			       usage_hint, bpp, &new_pitch))
743bfa90b6Smrg	goto out_no_driver_priv;
753bfa90b6Smrg
763bfa90b6Smrg    paddedWidth = new_pitch;
773bfa90b6Smrg    spix->damage = NULL;
783bfa90b6Smrg
793bfa90b6Smrg    /*
803bfa90b6Smrg     * Now set w and h to the correct value. This might allocate
813bfa90b6Smrg     * backing store if w and h are NON-NULL.
823bfa90b6Smrg     */
833bfa90b6Smrg
843bfa90b6Smrg    if (!(*pScreen->ModifyPixmapHeader) (pPixmap, w, h, 0, 0,
853bfa90b6Smrg					 paddedWidth, NULL))
863bfa90b6Smrg	goto out_no_pixmap_header;
873bfa90b6Smrg
883bfa90b6Smrg    /*
893bfa90b6Smrg     * During a fallback we must prepare access. This hack is initially used
903bfa90b6Smrg     * for pixmaps created during ValidateGC.
913bfa90b6Smrg     */
923bfa90b6Smrg
933bfa90b6Smrg    spix->fallback_created = FALSE;
943bfa90b6Smrg    if (sscreen->fallback_count) {
953bfa90b6Smrg	if (!saa_prepare_access_pixmap(pPixmap, SAA_ACCESS_W, NULL))
963bfa90b6Smrg	    goto out_no_access;
973bfa90b6Smrg
983bfa90b6Smrg	spix->fallback_created = TRUE;
993bfa90b6Smrg    }
1003bfa90b6Smrg
1013bfa90b6Smrg    return pPixmap;
1023bfa90b6Smrg out_no_access:
1033bfa90b6Smrg out_no_pixmap_header:
1043bfa90b6Smrg    driver->destroy_pixmap(driver, pPixmap);
1053bfa90b6Smrg out_no_driver_priv:
1063bfa90b6Smrg    saa_swap(sscreen, pScreen, DestroyPixmap);
1073bfa90b6Smrg    pScreen->DestroyPixmap(pPixmap);
1083bfa90b6Smrg    saa_swap(sscreen, pScreen, DestroyPixmap);
1093bfa90b6Smrg out_no_pix:
1103bfa90b6Smrg    LogMessage(X_ERROR, "Failing pixmap creation.\n");
1113bfa90b6Smrg    return NullPixmap;
1123bfa90b6Smrg}
1133bfa90b6Smrg
1143bfa90b6SmrgBool
1153bfa90b6Smrgsaa_destroy_pixmap(PixmapPtr pPixmap)
1163bfa90b6Smrg{
1173bfa90b6Smrg    ScreenPtr pScreen = pPixmap->drawable.pScreen;
1183bfa90b6Smrg    struct saa_screen_priv *sscreen = saa_screen(pScreen);
1193bfa90b6Smrg    Bool ret;
1203bfa90b6Smrg    struct saa_driver *driver = sscreen->driver;
1213bfa90b6Smrg
1223bfa90b6Smrg    if (pPixmap->refcnt == 1) {
1233bfa90b6Smrg	struct saa_pixmap *spix = saa_pixmap(pPixmap);
1243bfa90b6Smrg
1253bfa90b6Smrg	if (spix->fallback_created) {
1263bfa90b6Smrg	    if (!sscreen->fallback_count)
1273bfa90b6Smrg		LogMessage(X_ERROR, "Fallback pixmap destroyed outside "
1283bfa90b6Smrg			   "fallback.\n");
1293bfa90b6Smrg
1303bfa90b6Smrg	    saa_finish_access_pixmap(pPixmap, SAA_ACCESS_W);
1313bfa90b6Smrg	}
1323bfa90b6Smrg
1333bfa90b6Smrg	driver->destroy_pixmap(driver, pPixmap);
1343bfa90b6Smrg
1353bfa90b6Smrg	REGION_UNINIT(pScreen, &spix->dirty_hw);
1363bfa90b6Smrg	REGION_UNINIT(pScreen, &spix->dirty_shadow);
13725dbecb6Smrg	if (spix->damage)
13825dbecb6Smrg	    DamageDestroy(spix->damage);
1393bfa90b6Smrg    }
1403bfa90b6Smrg
1413bfa90b6Smrg    saa_swap(sscreen, pScreen, DestroyPixmap);
1423bfa90b6Smrg    ret = pScreen->DestroyPixmap(pPixmap);
1433bfa90b6Smrg    saa_swap(sscreen, pScreen, DestroyPixmap);
1443bfa90b6Smrg
1453bfa90b6Smrg    return ret;
1463bfa90b6Smrg}
1473bfa90b6Smrg
1483bfa90b6SmrgBool
1493bfa90b6Smrgsaa_modify_pixmap_header(PixmapPtr pPixmap, int width, int height, int depth,
1503bfa90b6Smrg			 int bitsPerPixel, int devKind, pointer pPixData)
1513bfa90b6Smrg{
1523bfa90b6Smrg    ScreenPtr pScreen;
1533bfa90b6Smrg    struct saa_screen_priv *sscreen;
1543bfa90b6Smrg    struct saa_pixmap *spix;
1553bfa90b6Smrg    struct saa_driver *driver;
1563bfa90b6Smrg    Bool ret = TRUE;
1573bfa90b6Smrg
1583bfa90b6Smrg    if (!pPixmap)
1593bfa90b6Smrg	return FALSE;
1603bfa90b6Smrg
1613bfa90b6Smrg    pScreen = pPixmap->drawable.pScreen;
1623bfa90b6Smrg    sscreen = saa_screen(pScreen);
1633bfa90b6Smrg    spix = saa_pixmap(pPixmap);
1643bfa90b6Smrg    driver = sscreen->driver;
1653bfa90b6Smrg
1663bfa90b6Smrg    if (spix && driver->modify_pixmap_header &&
1673bfa90b6Smrg	driver->modify_pixmap_header(pPixmap, width, height, depth,
1683bfa90b6Smrg				     bitsPerPixel, devKind, pPixData)) {
1693bfa90b6Smrg	spix->auth_loc = saa_loc_driver;
1703bfa90b6Smrg	spix->override = SAA_INVALID_ADDRESS;
1713bfa90b6Smrg	goto out;
1723bfa90b6Smrg    }
1733bfa90b6Smrg
1743bfa90b6Smrg    saa_swap(sscreen, pScreen, ModifyPixmapHeader);
1753bfa90b6Smrg    ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
1763bfa90b6Smrg				      bitsPerPixel, devKind, pPixData);
1773bfa90b6Smrg    saa_swap(sscreen, pScreen, ModifyPixmapHeader);
1783bfa90b6Smrg    spix->override = pPixmap->devPrivate.ptr;
1793bfa90b6Smrg    spix->auth_loc = saa_loc_override;
1803bfa90b6Smrg
1813bfa90b6Smrg out:
1823bfa90b6Smrg    pPixmap->devPrivate.ptr = NULL;
1833bfa90b6Smrg    return ret;
1843bfa90b6Smrg}
1853bfa90b6Smrg
1863bfa90b6Smrgstruct saa_pixmap *
1873bfa90b6Smrgsaa_get_saa_pixmap(PixmapPtr pPixmap)
1883bfa90b6Smrg{
1893bfa90b6Smrg    return saa_pixmap(pPixmap);
1903bfa90b6Smrg}
1913bfa90b6Smrg
1923bfa90b6Smrgvoid
1933bfa90b6Smrgsaa_pixmap_dirty(PixmapPtr pixmap, Bool hw, RegionPtr reg)
1943bfa90b6Smrg{
1953bfa90b6Smrg    struct saa_pixmap *spix = saa_pixmap(pixmap);
1963bfa90b6Smrg    struct saa_screen_priv *sscreen = saa_screen(pixmap->drawable.pScreen);
1973bfa90b6Smrg
1983bfa90b6Smrg    if (hw) {
1993bfa90b6Smrg	REGION_UNION(pixmap->drawable.pScreen, &spix->dirty_hw,
2003bfa90b6Smrg		     &spix->dirty_hw, reg);
2013bfa90b6Smrg	REGION_SUBTRACT(pixmap->drawable.pScreen, &spix->dirty_shadow,
2023bfa90b6Smrg			&spix->dirty_shadow, reg);
2033bfa90b6Smrg    } else {
2043bfa90b6Smrg	REGION_UNION(pixmap->drawable.pScreen, &spix->dirty_shadow,
2053bfa90b6Smrg		     &spix->dirty_shadow, reg);
2063bfa90b6Smrg	REGION_SUBTRACT(pixmap->drawable.pScreen, &spix->dirty_hw,
2073bfa90b6Smrg			&spix->dirty_hw, reg);
2083bfa90b6Smrg    }
2093bfa90b6Smrg
2103bfa90b6Smrg    sscreen->driver->damage(sscreen->driver, pixmap, hw, reg);
2113bfa90b6Smrg}
2123bfa90b6Smrg
2133bfa90b6Smrgvoid
2143bfa90b6Smrgsaa_drawable_dirty(DrawablePtr draw, Bool hw, RegionPtr reg)
2153bfa90b6Smrg{
2163bfa90b6Smrg    PixmapPtr pixmap;
2173bfa90b6Smrg    int x_offset, y_offset;
2183bfa90b6Smrg
2193bfa90b6Smrg    pixmap = saa_get_pixmap(draw, &x_offset, &y_offset);
2203bfa90b6Smrg    REGION_TRANSLATE(draw->pScreen, reg, x_offset, y_offset);
2213bfa90b6Smrg    saa_pixmap_dirty(pixmap, hw, reg);
2223bfa90b6Smrg    REGION_TRANSLATE(draw->pScreen, reg, -x_offset, -y_offset);
2233bfa90b6Smrg}
224