~ubuntu-branches/ubuntu/quantal/mesa/quantal

« back to all changes in this revision

Viewing changes to src/glx/apple/apple_glx_drawable.c

  • Committer: Bazaar Package Importer
  • Author(s): Christopher James Halse Rogers
  • Date: 2011-06-06 16:51:56 UTC
  • mfrom: (1.2.35 upstream) (3.3.13 sid)
  • Revision ID: james.westby@ubuntu.com-20110606165156-c6632o2ttkrgwcr6
Tags: 7.10.3-0ubuntu1
* New upstream 7.10.3 bugfix release.
 - Fixes infinite loop in GLSL compiler (LP: #788730)
* Merge with Debian unstable.  Remaining Ubuntu changes:
 - debian/control
    + Drop lesstif-dev from Build-Depends; it's in Universe.
    + Comment out GLw libs since it depends on lesstif-dev.
    + Drop i686 swx11 libgl package.
    + Add libdrm-dev to mesa-common-dev Depends.
  - debian/rules
    + Use --disable-glw for swx11 targets too.
    + Don't enable motif for swx11 targets.
    + Use lzma compression for binary debs to save CD space.
    + Drop unloved mach64 driver.
    + Install both r300/r300g and r600/r600g
    + Use --enable-shared-dricore to claw back CD space.
  - debian/patches
    + 100_no_abi_tag.patch
    + 101_ubuntu_hidden_glname.patch
    + 103_savage-expose_fbmodes_with_nonzero_alpha.patch
  - rules, libgl1-mesa-{glx,dev,swx11,swx11-dev}.install.in,
    libgl1-mesa-{glx,swx11}.{postinst,prerm}, libgl1-mesa-dev.links.in:
    Install libGL.so* in /usr/lib/mesa to allow things to work with
    alternatives.
  - debian/not-installed:
    + Drop i686 files; we don't build 686-optimised packages in the first
      place.
  - debian/gbp.conf
    + Point at Ubuntu branch to make git-buildpackage less narky.
  - debian/patches/105_use_shared_libdricore.patch, debian/rules:
    + Link DRI drivers against shared dricore routines to save CD space.
  - debian/patches/109_fix_length_of_glxgetfbconfigssgix.patch:
    Fix "BadLength (poly request too large or internal Xlib length" 
    when using non-C, non-en locales.  (LP 714280)
  - debian/patches/108_fix_leaks_dri2_screen_creation.patch: Cherrypick
    to fix some leaks in DRI2 screen creation failure paths.
  - 114_intel_dri_renderer_string.diff: Re-add "GEM" to the dri renderer
    string of the intel driver. (LP 753370)
  - 113_fix_tls.diff: Fix crashes in unrelated code due to TLS usage.
* debian/rules:
* debian/libgl1-mesa-dri-experimental.install.in:
  - Ship i915g in the experimental package.  We're already building it,
    and it's apparently now comparable to i915c.
* debian/control:
* debian/libgl1-mesa-dri-experimental.install.in:
* debian/libgl1-mesa-dri.install.linux.in:
  - Move nouveau gallium driver from -dri-experimental to -dri.  Upstream
    is no longer adamant that bugs should be ignored.  Try installing it by
    default to get a better Unity experience OOTB. (LP: #759562)
* debian/libgl1-mesa-dri-experimental.install.in:
* debian/libgl1-mesa-dri.install.linux.in:
  - Move r300/r600 classic drivers to -experimental.  They're not supported.
    Shave another ~1MB off the CD!
* debian/control:
  - Add new bison and flex build-depends.
* debian/patches/115_llvm_dynamic_linking.diff
  - Dynamically link DRI drivers to libllvm.  Saves ~6MiB per DRI driver.
* debian/rules:
* debian/patches/116_use_shared_galliumcore.diff:
* debian/libgl1-mesa-dri.install.in:
  - Link gallium DRI drivers against shared gallium routines to save CD
    space.
* Merge multiarch support branch:
  - Declare Breaks: against old versions of xserver-xorg-core and
    libgl1-mesa-glx that will look for DRI modules only in /usr/lib/dri.
  - Fix up the maintainer scripts to transition to per-architecture
    alternatives for ld.so configs.
  - Declare Breaks: against nvidia-current, nvidia-173, and fglrx due to the
    migration of alternatives for the ld.so.conf snippets.
  - Use multiarch dirs for our dri module search path, with a fallback to
    /usr/lib/dri.
  - Use the right path for dh_shlibdeps.  
* debian/patches/117_handle_dri2connect_errors_when_indirect.diff:
  - Handle BadRequest X protocol errors which DRI2 throws when remote
    clients attempt to connect so that mesa can fall back to a codepath
    that works. (LP: #785368)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 Copyright (c) 2008, 2009 Apple Inc.
 
3
 
 
4
 Permission is hereby granted, free of charge, to any person
 
5
 obtaining a copy of this software and associated documentation files
 
6
 (the "Software"), to deal in the Software without restriction,
 
7
 including without limitation the rights to use, copy, modify, merge,
 
8
 publish, distribute, sublicense, and/or sell copies of the Software,
 
9
 and to permit persons to whom the Software is furnished to do so,
 
10
 subject to the following conditions:
 
11
 
 
12
 The above copyright notice and this permission notice shall be
 
13
 included in all copies or substantial portions of the Software.
 
14
 
 
15
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
16
 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
17
 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 
18
 NONINFRINGEMENT.  IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
 
19
 HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 
20
 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
21
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 
22
 DEALINGS IN THE SOFTWARE.
 
23
 
 
24
 Except as contained in this notice, the name(s) of the above
 
25
 copyright holders shall not be used in advertising or otherwise to
 
26
 promote the sale, use or other dealings in this Software without
 
27
 prior written authorization.
 
28
*/
 
29
 
 
30
#include <stdbool.h>
 
31
#include <stdio.h>
 
32
#include <stdlib.h>
 
33
#include <assert.h>
 
34
#include <pthread.h>
 
35
#include "apple_glx.h"
 
36
#include "apple_glx_context.h"
 
37
#include "apple_glx_drawable.h"
 
38
#include "appledri.h"
 
39
 
 
40
static pthread_mutex_t drawables_lock = PTHREAD_MUTEX_INITIALIZER;
 
41
static struct apple_glx_drawable *drawables_list = NULL;
 
42
 
 
43
static void
 
44
lock_drawables_list(void)
 
45
{
 
46
   int err;
 
47
 
 
48
   err = pthread_mutex_lock(&drawables_lock);
 
49
 
 
50
   if (err) {
 
51
      fprintf(stderr, "pthread_mutex_lock failure in %s: %d\n",
 
52
              __func__, err);
 
53
      abort();
 
54
   }
 
55
}
 
56
 
 
57
static void
 
58
unlock_drawables_list(void)
 
59
{
 
60
   int err;
 
61
 
 
62
   err = pthread_mutex_unlock(&drawables_lock);
 
63
 
 
64
   if (err) {
 
65
      fprintf(stderr, "pthread_mutex_unlock failure in %s: %d\n",
 
66
              __func__, err);
 
67
      abort();
 
68
   }
 
69
}
 
70
 
 
71
struct apple_glx_drawable *
 
72
apple_glx_find_drawable(Display * dpy, GLXDrawable drawable)
 
73
{
 
74
   struct apple_glx_drawable *i, *agd = NULL;
 
75
 
 
76
   lock_drawables_list();
 
77
 
 
78
   for (i = drawables_list; i; i = i->next) {
 
79
      if (i->drawable == drawable) {
 
80
         agd = i;
 
81
         break;
 
82
      }
 
83
   }
 
84
 
 
85
   unlock_drawables_list();
 
86
 
 
87
   return agd;
 
88
}
 
89
 
 
90
static void
 
91
drawable_lock(struct apple_glx_drawable *agd)
 
92
{
 
93
   int err;
 
94
 
 
95
   err = pthread_mutex_lock(&agd->mutex);
 
96
 
 
97
   if (err) {
 
98
      fprintf(stderr, "pthread_mutex_lock error: %d\n", err);
 
99
      abort();
 
100
   }
 
101
}
 
102
 
 
103
static void
 
104
drawable_unlock(struct apple_glx_drawable *d)
 
105
{
 
106
   int err;
 
107
 
 
108
   err = pthread_mutex_unlock(&d->mutex);
 
109
 
 
110
   if (err) {
 
111
      fprintf(stderr, "pthread_mutex_unlock error: %d\n", err);
 
112
      abort();
 
113
   }
 
114
}
 
115
 
 
116
 
 
117
static void
 
118
reference_drawable(struct apple_glx_drawable *d)
 
119
{
 
120
   d->lock(d);
 
121
   d->reference_count++;
 
122
   d->unlock(d);
 
123
}
 
124
 
 
125
static void
 
126
release_drawable(struct apple_glx_drawable *d)
 
127
{
 
128
   d->lock(d);
 
129
   d->reference_count--;
 
130
   d->unlock(d);
 
131
}
 
132
 
 
133
/* The drawables list must be locked prior to calling this. */
 
134
/* Return true if the drawable was destroyed. */
 
135
static bool
 
136
destroy_drawable(struct apple_glx_drawable *d)
 
137
{
 
138
 
 
139
   d->lock(d);
 
140
 
 
141
   if (d->reference_count > 0) {
 
142
      d->unlock(d);
 
143
      return false;
 
144
   }
 
145
 
 
146
   d->unlock(d);
 
147
 
 
148
   if (d->previous) {
 
149
      d->previous->next = d->next;
 
150
   }
 
151
   else {
 
152
      /*
 
153
       * The item must be at the head of the list, if it
 
154
       * has no previous pointer. 
 
155
       */
 
156
      drawables_list = d->next;
 
157
   }
 
158
 
 
159
   if (d->next)
 
160
      d->next->previous = d->previous;
 
161
 
 
162
   unlock_drawables_list();
 
163
 
 
164
   if (d->callbacks.destroy) {
 
165
      /*
 
166
       * Warning: this causes other routines to be called (potentially)
 
167
       * from surface_notify_handler.  It's probably best to not have
 
168
       * any locks at this point locked.
 
169
       */
 
170
      d->callbacks.destroy(d->display, d);
 
171
   }
 
172
 
 
173
   apple_glx_diagnostic("%s: freeing %p\n", __func__, (void *) d);
 
174
 
 
175
   free(d);
 
176
 
 
177
   /* So that the locks are balanced and the caller correctly unlocks. */
 
178
   lock_drawables_list();
 
179
 
 
180
   return true;
 
181
}
 
182
 
 
183
/*
 
184
 * This is typically called when a context is destroyed or the current
 
185
 * drawable is made None.
 
186
 */
 
187
static bool
 
188
destroy_drawable_callback(struct apple_glx_drawable *d)
 
189
{
 
190
   bool result;
 
191
 
 
192
   d->lock(d);
 
193
 
 
194
   apple_glx_diagnostic("%s: %p ->reference_count before -- %d\n", __func__,
 
195
                        (void *) d, d->reference_count);
 
196
 
 
197
   d->reference_count--;
 
198
 
 
199
   if (d->reference_count > 0) {
 
200
      d->unlock(d);
 
201
      return false;
 
202
   }
 
203
 
 
204
   d->unlock(d);
 
205
 
 
206
   lock_drawables_list();
 
207
 
 
208
   result = destroy_drawable(d);
 
209
 
 
210
   unlock_drawables_list();
 
211
 
 
212
   return result;
 
213
}
 
214
 
 
215
static bool
 
216
is_pbuffer(struct apple_glx_drawable *d)
 
217
{
 
218
   return APPLE_GLX_DRAWABLE_PBUFFER == d->type;
 
219
}
 
220
 
 
221
static bool
 
222
is_pixmap(struct apple_glx_drawable *d)
 
223
{
 
224
   return APPLE_GLX_DRAWABLE_PIXMAP == d->type;
 
225
}
 
226
 
 
227
static void
 
228
common_init(Display * dpy, GLXDrawable drawable, struct apple_glx_drawable *d)
 
229
{
 
230
   int err;
 
231
   pthread_mutexattr_t attr;
 
232
 
 
233
   d->display = dpy;
 
234
   d->reference_count = 0;
 
235
   d->drawable = drawable;
 
236
   d->type = -1;
 
237
 
 
238
   err = pthread_mutexattr_init(&attr);
 
239
 
 
240
   if (err) {
 
241
      fprintf(stderr, "pthread_mutexattr_init error: %d\n", err);
 
242
      abort();
 
243
   }
 
244
 
 
245
   /* 
 
246
    * There are some patterns that require a recursive mutex,
 
247
    * when working with locks that protect the apple_glx_drawable,
 
248
    * and reference functions like ->reference, and ->release.
 
249
    */
 
250
   err = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
 
251
 
 
252
   if (err) {
 
253
      fprintf(stderr, "error: setting pthread mutex type: %d\n", err);
 
254
      abort();
 
255
   }
 
256
 
 
257
   err = pthread_mutex_init(&d->mutex, &attr);
 
258
 
 
259
   if (err) {
 
260
      fprintf(stderr, "pthread_mutex_init error: %d\n", err);
 
261
      abort();
 
262
   }
 
263
 
 
264
   (void) pthread_mutexattr_destroy(&attr);
 
265
 
 
266
   d->lock = drawable_lock;
 
267
   d->unlock = drawable_unlock;
 
268
 
 
269
   d->reference = reference_drawable;
 
270
   d->release = release_drawable;
 
271
 
 
272
   d->destroy = destroy_drawable_callback;
 
273
 
 
274
   d->is_pbuffer = is_pbuffer;
 
275
   d->is_pixmap = is_pixmap;
 
276
 
 
277
   d->width = -1;
 
278
   d->height = -1;
 
279
   d->row_bytes = 0;
 
280
   d->path[0] = '\0';
 
281
   d->fd = -1;
 
282
   d->buffer = NULL;
 
283
   d->buffer_length = 0;
 
284
 
 
285
   d->previous = NULL;
 
286
   d->next = NULL;
 
287
}
 
288
 
 
289
static void
 
290
link_tail(struct apple_glx_drawable *agd)
 
291
{
 
292
   lock_drawables_list();
 
293
 
 
294
   /* Link the new drawable into the global list. */
 
295
   agd->next = drawables_list;
 
296
 
 
297
   if (drawables_list)
 
298
      drawables_list->previous = agd;
 
299
 
 
300
   drawables_list = agd;
 
301
 
 
302
   unlock_drawables_list();
 
303
}
 
304
 
 
305
/*WARNING: this returns a locked and referenced object. */
 
306
bool
 
307
apple_glx_drawable_create(Display * dpy,
 
308
                          int screen,
 
309
                          GLXDrawable drawable,
 
310
                          struct apple_glx_drawable **agdResult,
 
311
                          struct apple_glx_drawable_callbacks *callbacks)
 
312
{
 
313
   struct apple_glx_drawable *d;
 
314
 
 
315
   d = calloc(1, sizeof *d);
 
316
 
 
317
   if (NULL == d) {
 
318
      perror("malloc");
 
319
      return true;
 
320
   }
 
321
 
 
322
   common_init(dpy, drawable, d);
 
323
   d->type = callbacks->type;
 
324
   d->callbacks = *callbacks;
 
325
 
 
326
   d->reference(d);
 
327
   d->lock(d);
 
328
 
 
329
   link_tail(d);
 
330
 
 
331
   apple_glx_diagnostic("%s: new drawable %p\n", __func__, (void *) d);
 
332
 
 
333
   *agdResult = d;
 
334
 
 
335
   return false;
 
336
}
 
337
 
 
338
static int error_count = 0;
 
339
 
 
340
static int
 
341
error_handler(Display * dpy, XErrorEvent * err)
 
342
{
 
343
   if (err->error_code == BadWindow) {
 
344
      ++error_count;
 
345
   }
 
346
 
 
347
   return 0;
 
348
}
 
349
 
 
350
void
 
351
apple_glx_garbage_collect_drawables(Display * dpy)
 
352
{
 
353
   struct apple_glx_drawable *d, *dnext;
 
354
   Window root;
 
355
   int x, y;
 
356
   unsigned int width, height, bd, depth;
 
357
   int (*old_handler) (Display *, XErrorEvent *);
 
358
 
 
359
 
 
360
   if (NULL == drawables_list)
 
361
      return;
 
362
 
 
363
   old_handler = XSetErrorHandler(error_handler);
 
364
 
 
365
   XSync(dpy, False);
 
366
 
 
367
   lock_drawables_list();
 
368
 
 
369
   for (d = drawables_list; d;) {
 
370
      dnext = d->next;
 
371
 
 
372
      d->lock(d);
 
373
 
 
374
      if (d->reference_count > 0) {
 
375
         /* 
 
376
          * Skip this, because some context still retains a reference 
 
377
          * to the drawable.
 
378
          */
 
379
         d->unlock(d);
 
380
         d = dnext;
 
381
         continue;
 
382
      }
 
383
 
 
384
      d->unlock(d);
 
385
 
 
386
      error_count = 0;
 
387
 
 
388
      /* 
 
389
       * Mesa uses XGetWindowAttributes, but some of these things are 
 
390
       * most definitely not Windows, and that's against the rules.
 
391
       * XGetGeometry on the other hand is legal with a Pixmap and Window.
 
392
       */
 
393
      XGetGeometry(dpy, d->drawable, &root, &x, &y, &width, &height, &bd,
 
394
                   &depth);
 
395
 
 
396
      if (error_count > 0) {
 
397
         /*
 
398
          * Note: this may not actually destroy the drawable.
 
399
          * If another context retains a reference to the drawable
 
400
          * after the reference count test above. 
 
401
          */
 
402
         (void) destroy_drawable(d);
 
403
         error_count = 0;
 
404
      }
 
405
 
 
406
      d = dnext;
 
407
   }
 
408
 
 
409
   XSetErrorHandler(old_handler);
 
410
 
 
411
   unlock_drawables_list();
 
412
}
 
413
 
 
414
unsigned int
 
415
apple_glx_get_drawable_count(void)
 
416
{
 
417
   unsigned int result = 0;
 
418
   struct apple_glx_drawable *d;
 
419
 
 
420
   lock_drawables_list();
 
421
 
 
422
   for (d = drawables_list; d; d = d->next)
 
423
      ++result;
 
424
 
 
425
   unlock_drawables_list();
 
426
 
 
427
   return result;
 
428
}
 
429
 
 
430
struct apple_glx_drawable *
 
431
apple_glx_drawable_find_by_type(GLXDrawable drawable, int type, int flags)
 
432
{
 
433
   struct apple_glx_drawable *d;
 
434
 
 
435
   lock_drawables_list();
 
436
 
 
437
   for (d = drawables_list; d; d = d->next) {
 
438
      if (d->type == type && d->drawable == drawable) {
 
439
         if (flags & APPLE_GLX_DRAWABLE_REFERENCE)
 
440
            d->reference(d);
 
441
 
 
442
         if (flags & APPLE_GLX_DRAWABLE_LOCK)
 
443
            d->lock(d);
 
444
 
 
445
         unlock_drawables_list();
 
446
 
 
447
         return d;
 
448
      }
 
449
   }
 
450
 
 
451
   unlock_drawables_list();
 
452
 
 
453
   return NULL;
 
454
}
 
455
 
 
456
struct apple_glx_drawable *
 
457
apple_glx_drawable_find(GLXDrawable drawable, int flags)
 
458
{
 
459
   struct apple_glx_drawable *d;
 
460
 
 
461
   lock_drawables_list();
 
462
 
 
463
   for (d = drawables_list; d; d = d->next) {
 
464
      if (d->drawable == drawable) {
 
465
         if (flags & APPLE_GLX_DRAWABLE_REFERENCE)
 
466
            d->reference(d);
 
467
 
 
468
         if (flags & APPLE_GLX_DRAWABLE_LOCK)
 
469
            d->lock(d);
 
470
 
 
471
         unlock_drawables_list();
 
472
 
 
473
         return d;
 
474
      }
 
475
   }
 
476
 
 
477
   unlock_drawables_list();
 
478
 
 
479
   return NULL;
 
480
}
 
481
 
 
482
/* Return true if the type is valid for the drawable. */
 
483
bool
 
484
apple_glx_drawable_destroy_by_type(Display * dpy,
 
485
                                   GLXDrawable drawable, int type)
 
486
{
 
487
   struct apple_glx_drawable *d;
 
488
 
 
489
   lock_drawables_list();
 
490
 
 
491
   for (d = drawables_list; d; d = d->next) {
 
492
      if (drawable == d->drawable && type == d->type) {
 
493
         /*
 
494
          * The user has requested that we destroy this resource.
 
495
          * However, there may be references in the contexts to it, so
 
496
          * release it, and call destroy_drawable which doesn't destroy
 
497
          * if the reference_count is > 0.
 
498
          */
 
499
         d->release(d);
 
500
 
 
501
         apple_glx_diagnostic("%s d->reference_count %d\n",
 
502
                              __func__, d->reference_count);
 
503
 
 
504
         destroy_drawable(d);
 
505
         unlock_drawables_list();
 
506
         return true;
 
507
      }
 
508
   }
 
509
 
 
510
   unlock_drawables_list();
 
511
 
 
512
   return false;
 
513
}
 
514
 
 
515
struct apple_glx_drawable *
 
516
apple_glx_drawable_find_by_uid(unsigned int uid, int flags)
 
517
{
 
518
   struct apple_glx_drawable *d;
 
519
 
 
520
   lock_drawables_list();
 
521
 
 
522
   for (d = drawables_list; d; d = d->next) {
 
523
      /* Only surfaces have a uid. */
 
524
      if (APPLE_GLX_DRAWABLE_SURFACE == d->type) {
 
525
         if (d->types.surface.uid == uid) {
 
526
            if (flags & APPLE_GLX_DRAWABLE_REFERENCE)
 
527
               d->reference(d);
 
528
 
 
529
            if (flags & APPLE_GLX_DRAWABLE_LOCK)
 
530
               d->lock(d);
 
531
 
 
532
            unlock_drawables_list();
 
533
 
 
534
            return d;
 
535
         }
 
536
      }
 
537
   }
 
538
 
 
539
   unlock_drawables_list();
 
540
 
 
541
   return NULL;
 
542
}