saa_pixmap.c revision 3bfa90b6
1/*
2 * Copyright © 2009 Maarten Maathuis
3 * Copyright 2011 VMWare, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Author: Based on "exa_driver.c"
26 * Author: Thomas Hellstrom <thellstrom@vmware.com>
27 */
28
29#include "saa_priv.h"
30#include "saa.h"
31
32PixmapPtr
33saa_create_pixmap(ScreenPtr pScreen, int w, int h, int depth,
34		  unsigned usage_hint)
35{
36    PixmapPtr pPixmap;
37    struct saa_pixmap *spix;
38    int bpp;
39    size_t paddedWidth;
40    struct saa_screen_priv *sscreen = saa_screen(pScreen);
41    int new_pitch = 0;
42    struct saa_driver *driver = sscreen->driver;
43
44    if (w > 32767 || h > 32767)
45	return NullPixmap;
46
47    /*
48     * Create a scratch pixmap without backing storage (w and h are zero)
49     */
50
51    saa_swap(sscreen, pScreen, CreatePixmap);
52    pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint);
53    saa_swap(sscreen, pScreen, CreatePixmap);
54
55    if (!pPixmap)
56	goto out_no_pix;
57
58    spix = saa_pixmap(pPixmap);
59    memset(spix, 0, driver->pixmap_size);
60    REGION_NULL(pScreen, &spix->dirty_shadow);
61    REGION_NULL(pScreen, &spix->dirty_hw);
62    REGION_NULL(pScreen, &spix->shadow_damage);
63    spix->read_access = 0;
64    spix->write_access = 0;
65    spix->mapped_access = 0;
66    spix->addr = NULL;
67    spix->auth_loc = saa_loc_override;
68    spix->override = SAA_INVALID_ADDRESS;
69    spix->pixmap = pPixmap;
70    bpp = pPixmap->drawable.bitsPerPixel;
71
72    if (!driver->create_pixmap(driver, spix, w, h, depth,
73			       usage_hint, bpp, &new_pitch))
74	goto out_no_driver_priv;
75
76    paddedWidth = new_pitch;
77    spix->damage = NULL;
78
79    /*
80     * Now set w and h to the correct value. This might allocate
81     * backing store if w and h are NON-NULL.
82     */
83
84    if (!(*pScreen->ModifyPixmapHeader) (pPixmap, w, h, 0, 0,
85					 paddedWidth, NULL))
86	goto out_no_pixmap_header;
87
88    /*
89     * During a fallback we must prepare access. This hack is initially used
90     * for pixmaps created during ValidateGC.
91     */
92
93    spix->fallback_created = FALSE;
94    if (sscreen->fallback_count) {
95	if (!saa_prepare_access_pixmap(pPixmap, SAA_ACCESS_W, NULL))
96	    goto out_no_access;
97
98	spix->fallback_created = TRUE;
99    }
100
101    return pPixmap;
102 out_no_access:
103 out_no_pixmap_header:
104    driver->destroy_pixmap(driver, pPixmap);
105 out_no_driver_priv:
106    saa_swap(sscreen, pScreen, DestroyPixmap);
107    pScreen->DestroyPixmap(pPixmap);
108    saa_swap(sscreen, pScreen, DestroyPixmap);
109 out_no_pix:
110    LogMessage(X_ERROR, "Failing pixmap creation.\n");
111    return NullPixmap;
112}
113
114Bool
115saa_destroy_pixmap(PixmapPtr pPixmap)
116{
117    ScreenPtr pScreen = pPixmap->drawable.pScreen;
118    struct saa_screen_priv *sscreen = saa_screen(pScreen);
119    Bool ret;
120    struct saa_driver *driver = sscreen->driver;
121
122    if (pPixmap->refcnt == 1) {
123	struct saa_pixmap *spix = saa_pixmap(pPixmap);
124
125	if (spix->fallback_created) {
126	    if (!sscreen->fallback_count)
127		LogMessage(X_ERROR, "Fallback pixmap destroyed outside "
128			   "fallback.\n");
129
130	    saa_finish_access_pixmap(pPixmap, SAA_ACCESS_W);
131	}
132
133	driver->destroy_pixmap(driver, pPixmap);
134
135	REGION_UNINIT(pScreen, &spix->dirty_hw);
136	REGION_UNINIT(pScreen, &spix->dirty_shadow);
137	spix->damage = NULL;
138    }
139
140    saa_swap(sscreen, pScreen, DestroyPixmap);
141    ret = pScreen->DestroyPixmap(pPixmap);
142    saa_swap(sscreen, pScreen, DestroyPixmap);
143
144    return ret;
145}
146
147Bool
148saa_modify_pixmap_header(PixmapPtr pPixmap, int width, int height, int depth,
149			 int bitsPerPixel, int devKind, pointer pPixData)
150{
151    ScreenPtr pScreen;
152    struct saa_screen_priv *sscreen;
153    struct saa_pixmap *spix;
154    struct saa_driver *driver;
155    Bool ret = TRUE;
156
157    if (!pPixmap)
158	return FALSE;
159
160    pScreen = pPixmap->drawable.pScreen;
161    sscreen = saa_screen(pScreen);
162    spix = saa_pixmap(pPixmap);
163    driver = sscreen->driver;
164
165    if (spix && driver->modify_pixmap_header &&
166	driver->modify_pixmap_header(pPixmap, width, height, depth,
167				     bitsPerPixel, devKind, pPixData)) {
168	spix->auth_loc = saa_loc_driver;
169	spix->override = SAA_INVALID_ADDRESS;
170	goto out;
171    }
172
173    saa_swap(sscreen, pScreen, ModifyPixmapHeader);
174    ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
175				      bitsPerPixel, devKind, pPixData);
176    saa_swap(sscreen, pScreen, ModifyPixmapHeader);
177    spix->override = pPixmap->devPrivate.ptr;
178    spix->auth_loc = saa_loc_override;
179
180 out:
181    pPixmap->devPrivate.ptr = NULL;
182    return ret;
183}
184
185struct saa_pixmap *
186saa_get_saa_pixmap(PixmapPtr pPixmap)
187{
188    return saa_pixmap(pPixmap);
189}
190
191void
192saa_pixmap_dirty(PixmapPtr pixmap, Bool hw, RegionPtr reg)
193{
194    struct saa_pixmap *spix = saa_pixmap(pixmap);
195    struct saa_screen_priv *sscreen = saa_screen(pixmap->drawable.pScreen);
196
197    if (hw) {
198	REGION_UNION(pixmap->drawable.pScreen, &spix->dirty_hw,
199		     &spix->dirty_hw, reg);
200	REGION_SUBTRACT(pixmap->drawable.pScreen, &spix->dirty_shadow,
201			&spix->dirty_shadow, reg);
202    } else {
203	REGION_UNION(pixmap->drawable.pScreen, &spix->dirty_shadow,
204		     &spix->dirty_shadow, reg);
205	REGION_SUBTRACT(pixmap->drawable.pScreen, &spix->dirty_hw,
206			&spix->dirty_hw, reg);
207    }
208
209    sscreen->driver->damage(sscreen->driver, pixmap, hw, reg);
210}
211
212void
213saa_drawable_dirty(DrawablePtr draw, Bool hw, RegionPtr reg)
214{
215    PixmapPtr pixmap;
216    int x_offset, y_offset;
217
218    pixmap = saa_get_pixmap(draw, &x_offset, &y_offset);
219    REGION_TRANSLATE(draw->pScreen, reg, x_offset, y_offset);
220    saa_pixmap_dirty(pixmap, hw, reg);
221    REGION_TRANSLATE(draw->pScreen, reg, -x_offset, -y_offset);
222}
223