Add patch that contain Mali fixes.
[deb_xorg-server.git] / debian / patches / xorg-server-005-mali_fixes.patch
1 --- a/hw/xfree86/dri2/dri2.c
2 +++ b/hw/xfree86/dri2/dri2.c
3 @@ -1,4 +1,4 @@
4 -/*
5 + /*
6 * Copyright © 2007, 2008 Red Hat, Inc.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 @@ -100,6 +100,7 @@ typedef struct _DRI2Drawable {
10 CARD64 last_swap_ust; /* ust at completion of most recent swap */
11 int swap_limit; /* for N-buffering */
12 Bool needInvalidate;
13 + Bool client_created;
14 int prime_id;
15 PixmapPtr prime_slave_pixmap;
16 PixmapPtr redirectpixmap;
17 @@ -114,6 +115,7 @@ typedef struct _DRI2Screen {
18 int fd;
19 unsigned int lastSequence;
20 int prime_id;
21 + Bool need_async_swapbuffers_reply;
22
23 DRI2CreateBufferProcPtr CreateBuffer;
24 DRI2DestroyBufferProcPtr DestroyBuffer;
25 @@ -201,6 +203,7 @@ DRI2AllocateDrawable(DrawablePtr pDraw)
26 if (pPriv == NULL)
27 return NULL;
28
29 + pPriv->client_created = FALSE;
30 pPriv->dri2_screen = ds;
31 pPriv->drawable = pDraw;
32 pPriv->width = pDraw->width;
33 @@ -328,6 +331,15 @@ DRI2CreateDrawable2(ClientPtr client, Dr
34 int rc;
35
36 pPriv = DRI2GetDrawable(pDraw);
37 + if (pPriv && dri2_id_out == NULL && pPriv->client_created) {
38 + /* We already allocated a DRI2Drawable for this drawable, the client
39 + * has called into this function (so will receive invalidate events)
40 + * and now we're being called by the client again (we know this because
41 + * the caller doesn't care about the dri2_id). This means we don't need
42 + * to allocate another one, we have nothing else to do. */
43 + pPriv->prime_id = dri2_client->prime_id;
44 + return Success;
45 + }
46 if (pPriv == NULL)
47 pPriv = DRI2AllocateDrawable(pDraw);
48 if (pPriv == NULL)
49 @@ -342,6 +354,11 @@ DRI2CreateDrawable2(ClientPtr client, Dr
50
51 if (dri2_id_out)
52 *dri2_id_out = dri2_id;
53 + else {
54 + /* The client has called in for the first time, it will now receive
55 + * invalidate events. Record this for later. */
56 + pPriv->client_created = TRUE;
57 + }
58
59 return Success;
60 }
61 @@ -1071,7 +1088,11 @@ DRI2WaitSwap(ClientPtr client, DrawableP
62 return FALSE;
63 }
64
65 -
66 +Bool
67 +DRI2NeedAsyncSwapBuffersReply(DrawablePtr pDraw)
68 +{
69 + return DRI2GetScreen(pDraw->pScreen)->need_async_swapbuffers_reply;
70 +}
71
72 int
73 DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
74 @@ -1516,6 +1537,12 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2In
75 if (!ds->driverNames)
76 goto err_out;
77 ds->driverNames[0] = info->driverName;
78 +
79 + /* Mali incorrectly assumes that a return from SwapBuffers means that
80 + * buffers have been swapped, it doesn't wait for the relevant event.
81 + * In this case, we work around this annoyance by delaying the
82 + * SwapBuffers reply until the swap has actually completed. */
83 + ds->need_async_swapbuffers_reply = strcmp(info->driverName, "armsoc") == 0;
84 }
85 else {
86 ds->numDrivers = info->numDrivers;
87 --- a/hw/xfree86/dri2/dri2ext.c
88 +++ b/hw/xfree86/dri2/dri2ext.c
89 @@ -53,6 +53,14 @@
90
91 static int DRI2EventBase;
92
93 +/* Data shared by ProcDRI2SwapBuffers and the asynchronous callback
94 + * DRI2SwapEvent */
95 +struct SwapBuffersData {
96 + CARD64 swap_target;
97 + int refcnt;
98 + DrawablePtr pDrawable;
99 + CARD16 sequence;
100 +};
101
102 static Bool
103 validDrawable(ClientPtr client, XID drawable, Mask access_mode,
104 @@ -276,7 +284,6 @@ ProcDRI2GetBuffers(ClientPtr client)
105
106 if (DRI2ThrottleClient(client, pDrawable))
107 return Success;
108 -
109 attachments = (unsigned int *) &stuff[1];
110 buffers = DRI2GetBuffers(pDrawable, &width, &height,
111 attachments, stuff->count, &count);
112 @@ -355,6 +362,24 @@ load_swap_reply(xDRI2SwapBuffersReply *
113 rep->swap_lo = sbc & 0xffffffff;
114 }
115
116 +static void swap_buffers_data_unref(struct SwapBuffersData *data)
117 +{
118 + if (--data->refcnt == 0)
119 + free(data);
120 +}
121 +
122 +static void send_swap_buffers_reply(ClientPtr client, struct SwapBuffersData *data)
123 +{
124 + xDRI2SwapBuffersReply rep = {
125 + .type = X_Reply,
126 + .length = 0,
127 + .sequenceNumber = data->sequence,
128 + };
129 +
130 + load_swap_reply(&rep, data->swap_target);
131 + WriteToClient(client, sizeof(xDRI2SwapBuffersReply), &rep);
132 +}
133 +
134 static CARD64
135 vals_to_card64(CARD32 lo, CARD32 hi)
136 {
137 @@ -365,11 +390,11 @@ static void
138 DRI2SwapEvent(ClientPtr client, void *data, int type, CARD64 ust, CARD64 msc,
139 CARD32 sbc)
140 {
141 - DrawablePtr pDrawable = data;
142 + struct SwapBuffersData *sbdata = data;
143 xDRI2BufferSwapComplete2 event = {
144 .type = DRI2EventBase + DRI2_BufferSwapComplete,
145 .event_type = type,
146 - .drawable = pDrawable->id,
147 + .drawable = sbdata->pDrawable->id,
148 .ust_hi = (CARD64) ust >> 32,
149 .ust_lo = ust & 0xffffffff,
150 .msc_hi = (CARD64) msc >> 32,
151 @@ -377,6 +402,12 @@ DRI2SwapEvent(ClientPtr client, void *da
152 .sbc = sbc
153 };
154
155 + if (DRI2NeedAsyncSwapBuffersReply(sbdata->pDrawable)) {
156 + send_swap_buffers_reply(client, sbdata);
157 + AttendClient(client);
158 + }
159 +
160 + swap_buffers_data_unref(data);
161 WriteEventsToClient(client, 1, (xEvent *) &event);
162 }
163
164 @@ -384,14 +415,11 @@ static int
165 ProcDRI2SwapBuffers(ClientPtr client)
166 {
167 REQUEST(xDRI2SwapBuffersReq);
168 - xDRI2SwapBuffersReply rep = {
169 - .type = X_Reply,
170 - .sequenceNumber = client->sequence,
171 - .length = 0
172 - };
173 DrawablePtr pDrawable;
174 - CARD64 target_msc, divisor, remainder, swap_target;
175 + CARD64 target_msc, divisor, remainder;
176 + struct SwapBuffersData *data;
177 int status;
178 + Bool need_async_swap_reply;
179
180 REQUEST_SIZE_MATCH(xDRI2SwapBuffersReq);
181
182 @@ -399,6 +427,8 @@ ProcDRI2SwapBuffers(ClientPtr client)
183 DixReadAccess | DixWriteAccess, &pDrawable, &status))
184 return status;
185
186 + need_async_swap_reply = DRI2NeedAsyncSwapBuffersReply(pDrawable);
187 +
188 /*
189 * Ensures an out of control client can't exhaust our swap queue, and
190 * also orders swaps.
191 @@ -406,18 +436,49 @@ ProcDRI2SwapBuffers(ClientPtr client)
192 if (DRI2ThrottleClient(client, pDrawable))
193 return Success;
194
195 + data = malloc(sizeof(struct SwapBuffersData));
196 + /* DRI2SwapEvent() above might feel like the obvious place to free the
197 + * data struct we just allocated. But consider the following sequence of
198 + * events (and understand that swap_target is stored in data):
199 + * 1. DRI2SwapBuffers accesses swap_target
200 + * 2. DRI2SwapBuffers calls into ScheduleSwap
201 + * 3. ScheduleSwap blits and calls DRI2SwapEvent before returning
202 + * 4. Back in DRI2SwapBuffers, we access swap_target again
203 + *
204 + * If we had freed data in step 3, we would have a use-after-free in
205 + * step 4.
206 + *
207 + * So, we set up a refcount of 2. One ref is owned by this function, and
208 + * one ref is owned by DRI2SwapEvent. We only free the data once both
209 + * functions are done. */
210 + data->refcnt = 2;
211 + data->pDrawable = pDrawable;
212 + data->sequence = client->sequence;
213 +
214 target_msc = vals_to_card64(stuff->target_msc_lo, stuff->target_msc_hi);
215 divisor = vals_to_card64(stuff->divisor_lo, stuff->divisor_hi);
216 remainder = vals_to_card64(stuff->remainder_lo, stuff->remainder_hi);
217
218 + /* If we're sending the reply later, we need to avoid processing any
219 + * more requests from this client until that point. */
220 + if (need_async_swap_reply)
221 + IgnoreClient(client);
222 +
223 status = DRI2SwapBuffers(client, pDrawable, target_msc, divisor, remainder,
224 - &swap_target, DRI2SwapEvent, pDrawable);
225 - if (status != Success)
226 + &data->swap_target, DRI2SwapEvent, data);
227 +
228 + if (status != Success) {
229 + swap_buffers_data_unref(data);
230 + swap_buffers_data_unref(data);
231 + if (need_async_swap_reply)
232 + AttendClient(client);
233 return BadDrawable;
234 + }
235
236 - load_swap_reply(&rep, swap_target);
237 + if (!need_async_swap_reply)
238 + send_swap_buffers_reply(client, data);
239
240 - WriteToClient(client, sizeof(xDRI2SwapBuffersReply), &rep);
241 + swap_buffers_data_unref(data);
242
243 return Success;
244 }
245 --- a/hw/xfree86/dri2/dri2.h
246 +++ b/hw/xfree86/dri2/dri2.h
247 @@ -359,4 +359,6 @@ extern _X_EXPORT int DRI2GetParam(Client
248 CARD64 *value);
249
250 extern _X_EXPORT DrawablePtr DRI2UpdatePrime(DrawablePtr pDraw, DRI2BufferPtr pDest);
251 +
252 +extern Bool DRI2NeedAsyncSwapBuffersReply(DrawablePtr pDraw);
253 #endif