Imported Upstream version 1.15.1
[deb_xorg-server.git] / dix / pixmap.c
CommitLineData
a09e091a
JB
1/*
2
3Copyright 1993, 1998 The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included
12in all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of The Open Group shall
23not be used in advertising or otherwise to promote the sale, use or
24other dealings in this Software without prior written authorization
25from The Open Group.
26
27*/
28
29#ifdef HAVE_DIX_CONFIG_H
30#include <dix-config.h>
31#endif
32
33#include <X11/X.h>
34#include "scrnintstr.h"
35#include "misc.h"
36#include "os.h"
37#include "windowstr.h"
38#include "resource.h"
39#include "dixstruct.h"
40#include "gcstruct.h"
41#include "servermd.h"
42#include "site.h"
43
44/*
45 * Scratch pixmap management and device independent pixmap allocation
46 * function.
47 */
48
49/* callable by ddx */
50PixmapPtr
51GetScratchPixmapHeader(ScreenPtr pScreen, int width, int height, int depth,
52 int bitsPerPixel, int devKind, pointer pPixData)
53{
54 PixmapPtr pPixmap = pScreen->pScratchPixmap;
55
56 if (pPixmap)
57 pScreen->pScratchPixmap = NULL;
58 else
59 /* width and height of 0 means don't allocate any pixmap data */
60 pPixmap = (*pScreen->CreatePixmap) (pScreen, 0, 0, depth, 0);
61
62 if (pPixmap) {
63 if ((*pScreen->ModifyPixmapHeader) (pPixmap, width, height, depth,
64 bitsPerPixel, devKind, pPixData))
65 return pPixmap;
66 (*pScreen->DestroyPixmap) (pPixmap);
67 }
68 return NullPixmap;
69}
70
71/* callable by ddx */
72void
73FreeScratchPixmapHeader(PixmapPtr pPixmap)
74{
75 if (pPixmap) {
76 ScreenPtr pScreen = pPixmap->drawable.pScreen;
77
78 pPixmap->devPrivate.ptr = NULL; /* lest ddx chases bad ptr */
79 if (pScreen->pScratchPixmap)
80 (*pScreen->DestroyPixmap) (pPixmap);
81 else
82 pScreen->pScratchPixmap = pPixmap;
83 }
84}
85
86Bool
87CreateScratchPixmapsForScreen(ScreenPtr pScreen)
88{
89 unsigned int pixmap_size;
90
91 pixmap_size = sizeof(PixmapRec) + dixScreenSpecificPrivatesSize(pScreen, PRIVATE_PIXMAP);
92 pScreen->totalPixmapSize =
93 BitmapBytePad(pixmap_size * 8);
94
95 /* let it be created on first use */
96 pScreen->pScratchPixmap = NULL;
97 return TRUE;
98}
99
100void
101FreeScratchPixmapsForScreen(ScreenPtr pScreen)
102{
103 FreeScratchPixmapHeader(pScreen->pScratchPixmap);
104}
105
106/* callable by ddx */
107PixmapPtr
108AllocatePixmap(ScreenPtr pScreen, int pixDataSize)
109{
110 PixmapPtr pPixmap;
111
112 assert(pScreen->totalPixmapSize > 0);
113
114 if (pScreen->totalPixmapSize > ((size_t) - 1) - pixDataSize)
115 return NullPixmap;
116
117 pPixmap = malloc(pScreen->totalPixmapSize + pixDataSize);
118 if (!pPixmap)
119 return NullPixmap;
120
121 dixInitScreenPrivates(pScreen, pPixmap, pPixmap + 1, PRIVATE_PIXMAP);
122 return pPixmap;
123}
124
125/* callable by ddx */
126void
127FreePixmap(PixmapPtr pPixmap)
128{
129 dixFiniPrivates(pPixmap, PRIVATE_PIXMAP);
130 free(pPixmap);
131}
132
133PixmapPtr PixmapShareToSlave(PixmapPtr pixmap, ScreenPtr slave)
134{
135 PixmapPtr spix;
136 int ret;
137 void *handle;
138 ScreenPtr master = pixmap->drawable.pScreen;
139 int depth = pixmap->drawable.depth;
140
141 ret = master->SharePixmapBacking(pixmap, slave, &handle);
142 if (ret == FALSE)
143 return NULL;
144
145 spix = slave->CreatePixmap(slave, 0, 0, depth,
146 CREATE_PIXMAP_USAGE_SHARED);
147 slave->ModifyPixmapHeader(spix, pixmap->drawable.width,
148 pixmap->drawable.height, depth, 0,
149 pixmap->devKind, NULL);
150
151 /* have the slave pixmap take a reference on the master pixmap
152 later we destroy them both at the same time */
153 pixmap->refcnt++;
154
155 spix->master_pixmap = pixmap;
156
157 ret = slave->SetSharedPixmapBacking(spix, handle);
158 if (ret == FALSE) {
159 slave->DestroyPixmap(spix);
160 return NULL;
161 }
162
163 return spix;
164}
165
166Bool
167PixmapStartDirtyTracking(PixmapPtr src,
168 PixmapPtr slave_dst,
169 int x, int y)
170{
171 ScreenPtr screen = src->drawable.pScreen;
172 PixmapDirtyUpdatePtr dirty_update;
173
174 dirty_update = calloc(1, sizeof(PixmapDirtyUpdateRec));
175 if (!dirty_update)
176 return FALSE;
177
178 dirty_update->src = src;
179 dirty_update->slave_dst = slave_dst;
180 dirty_update->x = x;
181 dirty_update->y = y;
182
183 dirty_update->damage = DamageCreate(NULL, NULL,
184 DamageReportNone,
185 TRUE, src->drawable.pScreen,
186 src->drawable.pScreen);
187 if (!dirty_update->damage) {
188 free(dirty_update);
189 return FALSE;
190 }
191
192 DamageRegister(&src->drawable, dirty_update->damage);
193 xorg_list_add(&dirty_update->ent, &screen->pixmap_dirty_list);
194 return TRUE;
195}
196
197Bool
198PixmapStopDirtyTracking(PixmapPtr src, PixmapPtr slave_dst)
199{
200 ScreenPtr screen = src->drawable.pScreen;
201 PixmapDirtyUpdatePtr ent, safe;
202
203 xorg_list_for_each_entry_safe(ent, safe, &screen->pixmap_dirty_list, ent) {
204 if (ent->src == src && ent->slave_dst == slave_dst) {
205 DamageDestroy(ent->damage);
206 xorg_list_del(&ent->ent);
207 free(ent);
208 }
209 }
210 return TRUE;
211}
212
213/*
214 * this function can possibly be improved and optimised, by clipping
215 * instead of iterating
216 */
217Bool PixmapSyncDirtyHelper(PixmapDirtyUpdatePtr dirty, RegionPtr dirty_region)
218{
219 ScreenPtr pScreen = dirty->src->drawable.pScreen;
220 int n;
221 BoxPtr b;
222 RegionPtr region = DamageRegion(dirty->damage);
223 GCPtr pGC;
224 PixmapPtr dst;
225 SourceValidateProcPtr SourceValidate;
226
227 /*
228 * SourceValidate is used by the software cursor code
229 * to pull the cursor off of the screen when reading
230 * bits from the frame buffer. Bypassing this function
231 * leaves the software cursor in place
232 */
233 SourceValidate = pScreen->SourceValidate;
234 pScreen->SourceValidate = NULL;
235
236 RegionTranslate(dirty_region, dirty->x, dirty->y);
237 RegionIntersect(dirty_region, dirty_region, region);
238
239 if (RegionNil(dirty_region)) {
240 RegionUninit(dirty_region);
241 return FALSE;
242 }
243
244 dst = dirty->slave_dst->master_pixmap;
245 if (!dst)
246 dst = dirty->slave_dst;
247
248 RegionTranslate(dirty_region, -dirty->x, -dirty->y);
249 n = RegionNumRects(dirty_region);
250 b = RegionRects(dirty_region);
251
252 pGC = GetScratchGC(dirty->src->drawable.depth, pScreen);
253 ValidateGC(&dst->drawable, pGC);
254
255 while (n--) {
256 BoxRec dst_box;
257 int w, h;
258
259 dst_box = *b;
260 w = dst_box.x2 - dst_box.x1;
261 h = dst_box.y2 - dst_box.y1;
262
263 pGC->ops->CopyArea(&dirty->src->drawable, &dst->drawable, pGC,
264 dirty->x + dst_box.x1, dirty->y + dst_box.y1, w, h, dst_box.x1, dst_box.y1);
265 b++;
266 }
267 FreeScratchGC(pGC);
268
269 pScreen->SourceValidate = SourceValidate;
270 return TRUE;
271}