~ubuntu-branches/ubuntu/natty/mesa/natty-proposed

« back to all changes in this revision

Viewing changes to src/gallium/state_trackers/dri/drm/dri2.c

  • Committer: Bazaar Package Importer
  • Author(s): Robert Hooker, Robert Hooker, Christopher James Halse Rogers
  • Date: 2010-09-14 08:55:40 UTC
  • mfrom: (1.2.28 upstream)
  • Revision ID: james.westby@ubuntu.com-20100914085540-m4fpl0hdjlfd4jgz
Tags: 7.9~git20100909-0ubuntu1
[ Robert Hooker ]
* New upstream git snapshot up to commit 94118fe2d4b1e5 (LP: #631413)
* New features include ATI HD5xxx series support in r600, and a vastly
  improved glsl compiler.
* Remove pre-generated .pc's, use the ones generated at build time
  instead.
* Remove all references to mesa-utils now that its no longer shipped
  with the mesa source.
* Disable the experimental ARB_fragment_shader option by default on
  i915, it exposes incomplete functionality that breaks KDE compositing
  among other things. It can be enabled via driconf still. (LP: #628930).

[ Christopher James Halse Rogers ]
* debian/patches/04_osmesa_version.diff:
  - Refresh for new upstream
* Bugs fixed in this release:
  - Fixes severe rendering corruption in Unity on radeon (LP: #628727,
    LP: #596292, LP: #599741, LP: #630315, LP: #613694, LP: #599741).
  - Also fixes rendering in gnome-shell (LP: #578619).
  - Flickering in OpenGL apps on radeon (LP: #626943, LP: #610541).
  - Provides preliminary support for new intel chips (LP: #601052).
* debian/rules:
  - Update configure flags to match upstream reshuffling.
  - Explicitly remove gallium DRI drivers that we don't want to ship.
* Update debian/gbp.conf for this Maverick-specific packaging
* libegl1-mesa-dri-x11,kms: There are no longer separate kms or x11 drivers
  for EGL, libegl1-mesa-drivers now contains a single driver that provides
  both backends.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Mesa 3-D graphics library
 
3
 * Version:  7.9
 
4
 *
 
5
 * Copyright 2009, VMware, Inc.
 
6
 * All Rights Reserved.
 
7
 * Copyright (C) 2010 LunarG Inc.
 
8
 *
 
9
 * Permission is hereby granted, free of charge, to any person obtaining a
 
10
 * copy of this software and associated documentation files (the "Software"),
 
11
 * to deal in the Software without restriction, including without limitation
 
12
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 
13
 * and/or sell copies of the Software, and to permit persons to whom the
 
14
 * Software is furnished to do so, subject to the following conditions:
 
15
 *
 
16
 * The above copyright notice and this permission notice shall be included
 
17
 * in all copies or substantial portions of the Software.
 
18
 *
 
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 
20
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
21
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 
22
 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 
23
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
24
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
25
 *
 
26
 * Authors:
 
27
 *    Keith Whitwell <keithw@vmware.com>
 
28
 *    Jakob Bornecrantz <wallbraker@gmail.com>
 
29
 *    Chia-I Wu <olv@lunarg.com>
 
30
 */
 
31
 
 
32
#include "util/u_memory.h"
 
33
#include "util/u_inlines.h"
 
34
#include "util/u_format.h"
 
35
#include "util/u_debug.h"
 
36
#include "state_tracker/drm_driver.h"
 
37
 
 
38
#include "dri_screen.h"
 
39
#include "dri_context.h"
 
40
#include "dri_drawable.h"
 
41
 
 
42
/**
 
43
 * DRI2 flush extension.
 
44
 */
 
45
static void
 
46
dri2_flush_drawable(__DRIdrawable *draw)
 
47
{
 
48
}
 
49
 
 
50
static void
 
51
dri2_invalidate_drawable(__DRIdrawable *dPriv)
 
52
{
 
53
   struct dri_drawable *drawable = dri_drawable(dPriv);
 
54
   struct dri_context *ctx = dri_context(dPriv->driContextPriv);
 
55
 
 
56
   dri2InvalidateDrawable(dPriv);
 
57
   drawable->dPriv->lastStamp = *drawable->dPriv->pStamp;
 
58
 
 
59
   if (ctx)
 
60
      ctx->st->notify_invalid_framebuffer(ctx->st, &drawable->base);
 
61
}
 
62
 
 
63
static const __DRI2flushExtension dri2FlushExtension = {
 
64
    { __DRI2_FLUSH, __DRI2_FLUSH_VERSION },
 
65
    dri2_flush_drawable,
 
66
    dri2_invalidate_drawable,
 
67
};
 
68
 
 
69
/**
 
70
 * Retrieve __DRIbuffer from the DRI loader.
 
71
 */
 
72
static __DRIbuffer *
 
73
dri2_drawable_get_buffers(struct dri_drawable *drawable,
 
74
                          const enum st_attachment_type *statts,
 
75
                          unsigned *count)
 
76
{
 
77
   __DRIdrawable *dri_drawable = drawable->dPriv;
 
78
   struct __DRIdri2LoaderExtensionRec *loader = drawable->sPriv->dri2.loader;
 
79
   boolean with_format;
 
80
   __DRIbuffer *buffers;
 
81
   int num_buffers;
 
82
   unsigned attachments[10];
 
83
   unsigned num_attachments, i;
 
84
 
 
85
   assert(loader);
 
86
   with_format = dri_with_format(drawable->sPriv);
 
87
 
 
88
   num_attachments = 0;
 
89
 
 
90
   /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */
 
91
   if (!with_format)
 
92
      attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT;
 
93
 
 
94
   for (i = 0; i < *count; i++) {
 
95
      enum pipe_format format;
 
96
      unsigned bind;
 
97
      int att, bpp;
 
98
 
 
99
      dri_drawable_get_format(drawable, statts[i], &format, &bind);
 
100
      if (format == PIPE_FORMAT_NONE)
 
101
         continue;
 
102
 
 
103
      switch (statts[i]) {
 
104
      case ST_ATTACHMENT_FRONT_LEFT:
 
105
         /* already added */
 
106
         if (!with_format)
 
107
            continue;
 
108
         att = __DRI_BUFFER_FRONT_LEFT;
 
109
         break;
 
110
      case ST_ATTACHMENT_BACK_LEFT:
 
111
         att = __DRI_BUFFER_BACK_LEFT;
 
112
         break;
 
113
      case ST_ATTACHMENT_FRONT_RIGHT:
 
114
         att = __DRI_BUFFER_FRONT_RIGHT;
 
115
         break;
 
116
      case ST_ATTACHMENT_BACK_RIGHT:
 
117
         att = __DRI_BUFFER_BACK_RIGHT;
 
118
         break;
 
119
      case ST_ATTACHMENT_DEPTH_STENCIL:
 
120
         att = __DRI_BUFFER_DEPTH_STENCIL;
 
121
         break;
 
122
      default:
 
123
         att = -1;
 
124
         break;
 
125
      }
 
126
 
 
127
      bpp = util_format_get_blocksizebits(format);
 
128
 
 
129
      if (att >= 0) {
 
130
         attachments[num_attachments++] = att;
 
131
         if (with_format) {
 
132
            attachments[num_attachments++] = bpp;
 
133
         }
 
134
      }
 
135
   }
 
136
 
 
137
   if (with_format) {
 
138
      num_attachments /= 2;
 
139
      buffers = loader->getBuffersWithFormat(dri_drawable,
 
140
            &dri_drawable->w, &dri_drawable->h,
 
141
            attachments, num_attachments,
 
142
            &num_buffers, dri_drawable->loaderPrivate);
 
143
   }
 
144
   else {
 
145
      buffers = loader->getBuffers(dri_drawable,
 
146
            &dri_drawable->w, &dri_drawable->h,
 
147
            attachments, num_attachments,
 
148
            &num_buffers, dri_drawable->loaderPrivate);
 
149
   }
 
150
 
 
151
   if (buffers) {
 
152
      /* set one cliprect to cover the whole dri_drawable */
 
153
      dri_drawable->x = 0;
 
154
      dri_drawable->y = 0;
 
155
      dri_drawable->backX = 0;
 
156
      dri_drawable->backY = 0;
 
157
      dri_drawable->numClipRects = 1;
 
158
      dri_drawable->pClipRects[0].x1 = 0;
 
159
      dri_drawable->pClipRects[0].y1 = 0;
 
160
      dri_drawable->pClipRects[0].x2 = dri_drawable->w;
 
161
      dri_drawable->pClipRects[0].y2 = dri_drawable->h;
 
162
      dri_drawable->numBackClipRects = 1;
 
163
      dri_drawable->pBackClipRects[0].x1 = 0;
 
164
      dri_drawable->pBackClipRects[0].y1 = 0;
 
165
      dri_drawable->pBackClipRects[0].x2 = dri_drawable->w;
 
166
      dri_drawable->pBackClipRects[0].y2 = dri_drawable->h;
 
167
 
 
168
      *count = num_buffers;
 
169
   }
 
170
 
 
171
   return buffers;
 
172
}
 
173
 
 
174
/**
 
175
 * Process __DRIbuffer and convert them into pipe_resources.
 
176
 */
 
177
static void
 
178
dri2_drawable_process_buffers(struct dri_drawable *drawable,
 
179
                              __DRIbuffer *buffers, unsigned count)
 
180
{
 
181
   struct dri_screen *screen = dri_screen(drawable->sPriv);
 
182
   __DRIdrawable *dri_drawable = drawable->dPriv;
 
183
   struct pipe_resource templ;
 
184
   struct winsys_handle whandle;
 
185
   boolean have_depth = FALSE;
 
186
   unsigned i, bind;
 
187
 
 
188
   if (drawable->old_num == count &&
 
189
       drawable->old_w == dri_drawable->w &&
 
190
       drawable->old_h == dri_drawable->h &&
 
191
       memcmp(drawable->old, buffers, sizeof(__DRIbuffer) * count) == 0)
 
192
      return;
 
193
 
 
194
   for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
 
195
      pipe_resource_reference(&drawable->textures[i], NULL);
 
196
 
 
197
   memset(&templ, 0, sizeof(templ));
 
198
   templ.target = screen->target;
 
199
   templ.last_level = 0;
 
200
   templ.width0 = dri_drawable->w;
 
201
   templ.height0 = dri_drawable->h;
 
202
   templ.depth0 = 1;
 
203
 
 
204
   memset(&whandle, 0, sizeof(whandle));
 
205
 
 
206
   for (i = 0; i < count; i++) {
 
207
      __DRIbuffer *buf = &buffers[i];
 
208
      enum st_attachment_type statt;
 
209
      enum pipe_format format;
 
210
 
 
211
      switch (buf->attachment) {
 
212
      case __DRI_BUFFER_FRONT_LEFT:
 
213
         if (!screen->auto_fake_front) {
 
214
            statt = ST_ATTACHMENT_INVALID;
 
215
            break;
 
216
         }
 
217
         /* fallthrough */
 
218
      case __DRI_BUFFER_FAKE_FRONT_LEFT:
 
219
         statt = ST_ATTACHMENT_FRONT_LEFT;
 
220
         break;
 
221
      case __DRI_BUFFER_BACK_LEFT:
 
222
         statt = ST_ATTACHMENT_BACK_LEFT;
 
223
         break;
 
224
      case __DRI_BUFFER_DEPTH:
 
225
      case __DRI_BUFFER_DEPTH_STENCIL:
 
226
      case __DRI_BUFFER_STENCIL:
 
227
         /* use only the first depth/stencil buffer */
 
228
         if (!have_depth) {
 
229
            have_depth = TRUE;
 
230
            statt = ST_ATTACHMENT_DEPTH_STENCIL;
 
231
         }
 
232
         else {
 
233
            statt = ST_ATTACHMENT_INVALID;
 
234
         }
 
235
         break;
 
236
      default:
 
237
         statt = ST_ATTACHMENT_INVALID;
 
238
         break;
 
239
      }
 
240
 
 
241
      dri_drawable_get_format(drawable, statt, &format, &bind);
 
242
      if (statt == ST_ATTACHMENT_INVALID || format == PIPE_FORMAT_NONE)
 
243
         continue;
 
244
 
 
245
      templ.format = format;
 
246
      templ.bind = bind;
 
247
      whandle.handle = buf->name;
 
248
      whandle.stride = buf->pitch;
 
249
 
 
250
      drawable->textures[statt] =
 
251
         screen->base.screen->resource_from_handle(screen->base.screen,
 
252
               &templ, &whandle);
 
253
   }
 
254
 
 
255
   drawable->old_num = count;
 
256
   drawable->old_w = dri_drawable->w;
 
257
   drawable->old_h = dri_drawable->h;
 
258
   memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * count);
 
259
}
 
260
 
 
261
/*
 
262
 * Backend functions for st_framebuffer interface.
 
263
 */
 
264
 
 
265
static void
 
266
dri2_allocate_textures(struct dri_drawable *drawable,
 
267
                       const enum st_attachment_type *statts,
 
268
                       unsigned count)
 
269
{
 
270
   __DRIbuffer *buffers;
 
271
   unsigned num_buffers = count;
 
272
 
 
273
   buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers);
 
274
   if (buffers)
 
275
      dri2_drawable_process_buffers(drawable, buffers, num_buffers);
 
276
}
 
277
 
 
278
static void
 
279
dri2_flush_frontbuffer(struct dri_drawable *drawable,
 
280
                       enum st_attachment_type statt)
 
281
{
 
282
   __DRIdrawable *dri_drawable = drawable->dPriv;
 
283
   struct __DRIdri2LoaderExtensionRec *loader = drawable->sPriv->dri2.loader;
 
284
 
 
285
   if (loader->flushFrontBuffer == NULL)
 
286
      return;
 
287
 
 
288
   if (statt == ST_ATTACHMENT_FRONT_LEFT) {
 
289
      loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
 
290
   }
 
291
}
 
292
 
 
293
static __DRIimage *
 
294
dri2_lookup_egl_image(struct dri_context *ctx, void *handle)
 
295
{
 
296
   __DRIimageLookupExtension *loader = ctx->sPriv->dri2.image;
 
297
   __DRIimage *img;
 
298
 
 
299
   if (!loader->lookupEGLImage)
 
300
      return NULL;
 
301
 
 
302
   img = loader->lookupEGLImage(ctx->cPriv, handle, ctx->cPriv->loaderPrivate);
 
303
 
 
304
   return img;
 
305
}
 
306
 
 
307
static __DRIimage *
 
308
dri2_create_image_from_name(__DRIcontext *context,
 
309
                            int width, int height, int format,
 
310
                            int name, int pitch, void *loaderPrivate)
 
311
{
 
312
   struct dri_screen *screen = dri_screen(context->driScreenPriv);
 
313
   __DRIimage *img;
 
314
   struct pipe_resource templ;
 
315
   struct winsys_handle whandle;
 
316
   unsigned tex_usage;
 
317
   enum pipe_format pf;
 
318
 
 
319
   tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
 
320
 
 
321
   switch (format) {
 
322
   case __DRI_IMAGE_FORMAT_RGB565:
 
323
      pf = PIPE_FORMAT_B5G6R5_UNORM;
 
324
      break;
 
325
   case __DRI_IMAGE_FORMAT_XRGB8888:
 
326
      pf = PIPE_FORMAT_B8G8R8X8_UNORM;
 
327
      break;
 
328
   case __DRI_IMAGE_FORMAT_ARGB8888:
 
329
      pf = PIPE_FORMAT_B8G8R8A8_UNORM;
 
330
      break;
 
331
   default:
 
332
      pf = PIPE_FORMAT_NONE;
 
333
      break;
 
334
   }
 
335
   if (pf == PIPE_FORMAT_NONE)
 
336
      return NULL;
 
337
 
 
338
   img = CALLOC_STRUCT(__DRIimageRec);
 
339
   if (!img)
 
340
      return NULL;
 
341
 
 
342
   memset(&templ, 0, sizeof(templ));
 
343
   templ.bind = tex_usage;
 
344
   templ.format = pf;
 
345
   templ.target = screen->target;
 
346
   templ.last_level = 0;
 
347
   templ.width0 = width;
 
348
   templ.height0 = height;
 
349
   templ.depth0 = 1;
 
350
 
 
351
   memset(&whandle, 0, sizeof(whandle));
 
352
   whandle.handle = name;
 
353
   whandle.stride = pitch * util_format_get_blocksize(pf);
 
354
 
 
355
   img->texture = screen->base.screen->resource_from_handle(screen->base.screen,
 
356
         &templ, &whandle);
 
357
   if (!img->texture) {
 
358
      FREE(img);
 
359
      return NULL;
 
360
   }
 
361
 
 
362
   img->face = 0;
 
363
   img->level = 0;
 
364
   img->zslice = 0;
 
365
   img->loader_private = loaderPrivate;
 
366
 
 
367
   return img;
 
368
}
 
369
 
 
370
static __DRIimage *
 
371
dri2_create_image_from_renderbuffer(__DRIcontext *context,
 
372
                                    int renderbuffer, void *loaderPrivate)
 
373
{
 
374
   struct dri_context *ctx = dri_context(context->driverPrivate);
 
375
 
 
376
   if (!ctx->st->get_resource_for_egl_image)
 
377
      return NULL;
 
378
 
 
379
   /* TODO */
 
380
   return NULL;
 
381
}
 
382
 
 
383
static void
 
384
dri2_destroy_image(__DRIimage *img)
 
385
{
 
386
   pipe_resource_reference(&img->texture, NULL);
 
387
   FREE(img);
 
388
}
 
389
 
 
390
static struct __DRIimageExtensionRec dri2ImageExtension = {
 
391
    { __DRI_IMAGE, __DRI_IMAGE_VERSION },
 
392
    dri2_create_image_from_name,
 
393
    dri2_create_image_from_renderbuffer,
 
394
    dri2_destroy_image,
 
395
};
 
396
 
 
397
/*
 
398
 * Backend function init_screen.
 
399
 */
 
400
 
 
401
static const __DRIextension *dri_screen_extensions[] = {
 
402
   &driReadDrawableExtension,
 
403
   &driCopySubBufferExtension.base,
 
404
   &driSwapControlExtension.base,
 
405
   &driMediaStreamCounterExtension.base,
 
406
   &driTexBufferExtension.base,
 
407
   &dri2FlushExtension.base,
 
408
   &dri2ImageExtension.base,
 
409
   &dri2ConfigQueryExtension.base,
 
410
   NULL
 
411
};
 
412
 
 
413
/**
 
414
 * This is the driver specific part of the createNewScreen entry point.
 
415
 *
 
416
 * Returns the __GLcontextModes supported by this driver.
 
417
 */
 
418
static const __DRIconfig **
 
419
dri2_init_screen(__DRIscreen * sPriv)
 
420
{
 
421
   const __DRIconfig **configs;
 
422
   struct dri_screen *screen;
 
423
   struct pipe_screen *pscreen;
 
424
 
 
425
   screen = CALLOC_STRUCT(dri_screen);
 
426
   if (!screen)
 
427
      return NULL;
 
428
 
 
429
   screen->sPriv = sPriv;
 
430
   screen->fd = sPriv->fd;
 
431
 
 
432
   sPriv->private = (void *)screen;
 
433
   sPriv->extensions = dri_screen_extensions;
 
434
 
 
435
   pscreen = driver_descriptor.create_screen(screen->fd);
 
436
   /* dri_init_screen_helper checks pscreen for us */
 
437
 
 
438
   configs = dri_init_screen_helper(screen, pscreen, 32);
 
439
   if (!configs)
 
440
      goto fail;
 
441
 
 
442
   sPriv->api_mask = 0;
 
443
   if (screen->st_api[ST_API_OPENGL])
 
444
      sPriv->api_mask |= 1 << __DRI_API_OPENGL;
 
445
   if (screen->st_api[ST_API_OPENGL_ES1])
 
446
      sPriv->api_mask |= 1 << __DRI_API_GLES;
 
447
   if (screen->st_api[ST_API_OPENGL_ES2])
 
448
      sPriv->api_mask |= 1 << __DRI_API_GLES2;
 
449
 
 
450
   screen->auto_fake_front = dri_with_format(sPriv);
 
451
   screen->broken_invalidate = !sPriv->dri2.useInvalidate;
 
452
 
 
453
   return configs;
 
454
fail:
 
455
   dri_destroy_screen_helper(screen);
 
456
   FREE(screen);
 
457
   return NULL;
 
458
}
 
459
 
 
460
static boolean
 
461
dri2_create_context(gl_api api, const __GLcontextModes * visual,
 
462
                    __DRIcontext * cPriv, void *sharedContextPrivate)
 
463
{
 
464
   struct dri_context *ctx = NULL;
 
465
 
 
466
   if (!dri_create_context(api, visual, cPriv, sharedContextPrivate))
 
467
      return FALSE;
 
468
 
 
469
   ctx = cPriv->driverPrivate;
 
470
 
 
471
   ctx->lookup_egl_image = dri2_lookup_egl_image;
 
472
 
 
473
   return TRUE;
 
474
}
 
475
 
 
476
static boolean
 
477
dri2_create_buffer(__DRIscreen * sPriv,
 
478
                   __DRIdrawable * dPriv,
 
479
                   const __GLcontextModes * visual, boolean isPixmap)
 
480
{
 
481
   struct dri_drawable *drawable = NULL;
 
482
 
 
483
   if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap))
 
484
      return FALSE;
 
485
 
 
486
   drawable = dPriv->driverPrivate;
 
487
 
 
488
   drawable->allocate_textures = dri2_allocate_textures;
 
489
   drawable->flush_frontbuffer = dri2_flush_frontbuffer;
 
490
 
 
491
   return TRUE;
 
492
}
 
493
 
 
494
/**
 
495
 * DRI driver virtual function table.
 
496
 *
 
497
 * DRI versions differ in their implementation of init_screen and swap_buffers.
 
498
 */
 
499
const struct __DriverAPIRec driDriverAPI = {
 
500
   .InitScreen = NULL,
 
501
   .InitScreen2 = dri2_init_screen,
 
502
   .DestroyScreen = dri_destroy_screen,
 
503
   .CreateContext = dri2_create_context,
 
504
   .DestroyContext = dri_destroy_context,
 
505
   .CreateBuffer = dri2_create_buffer,
 
506
   .DestroyBuffer = dri_destroy_buffer,
 
507
   .MakeCurrent = dri_make_current,
 
508
   .UnbindContext = dri_unbind_context,
 
509
 
 
510
   .GetSwapInfo = NULL,
 
511
   .GetDrawableMSC = NULL,
 
512
   .WaitForMSC = NULL,
 
513
 
 
514
   .SwapBuffers = NULL,
 
515
   .CopySubBuffer = NULL,
 
516
};
 
517
 
 
518
/* This is the table of extensions that the loader will dlsym() for. */
 
519
PUBLIC const __DRIextension *__driDriverExtensions[] = {
 
520
    &driCoreExtension.base,
 
521
    &driLegacyExtension.base,
 
522
    &driDRI2Extension.base,
 
523
    NULL
 
524
};
 
525
 
 
526
/* vim: set sw=3 ts=8 sts=3 expandtab: */