Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / gallium / state_trackers / dri / drm / dri2.c
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 #include "dri2_buffer.h"
42
43 /**
44  * DRI2 flush extension.
45  */
46 static void
47 dri2_flush_drawable(__DRIdrawable *draw)
48 {
49 }
50
51 static void
52 dri2_invalidate_drawable(__DRIdrawable *dPriv)
53 {
54    struct dri_drawable *drawable = dri_drawable(dPriv);
55    struct dri_context *ctx = drawable->context;
56
57    dri2InvalidateDrawable(dPriv);
58    drawable->dPriv->lastStamp = *drawable->dPriv->pStamp;
59
60    if (ctx)
61       ctx->st->notify_invalid_framebuffer(ctx->st, &drawable->base);
62 }
63
64 static const __DRI2flushExtension dri2FlushExtension = {
65     { __DRI2_FLUSH, __DRI2_FLUSH_VERSION },
66     dri2_flush_drawable,
67     dri2_invalidate_drawable,
68 };
69
70 /**
71  * Retrieve __DRIbuffer from the DRI loader.
72  */
73 static __DRIbuffer *
74 dri2_drawable_get_buffers(struct dri_drawable *drawable,
75                           const enum st_attachment_type *statts,
76                           unsigned *count)
77 {
78    __DRIdrawable *dri_drawable = drawable->dPriv;
79    struct __DRIdri2LoaderExtensionRec *loader = drawable->sPriv->dri2.loader;
80    boolean with_format;
81    __DRIbuffer *buffers;
82    int num_buffers;
83    unsigned attachments[10];
84    unsigned num_attachments, i;
85
86    assert(loader);
87    with_format = dri_with_format(drawable->sPriv);
88
89    num_attachments = 0;
90
91    /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */
92    if (!with_format)
93       attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT;
94
95    for (i = 0; i < *count; i++) {
96       enum pipe_format format;
97       unsigned bind;
98       int att, bpp;
99
100       dri_drawable_get_format(drawable, statts[i], &format, &bind);
101       if (format == PIPE_FORMAT_NONE)
102          continue;
103
104       switch (statts[i]) {
105       case ST_ATTACHMENT_FRONT_LEFT:
106          /* already added */
107          if (!with_format)
108             continue;
109          att = __DRI_BUFFER_FRONT_LEFT;
110          break;
111       case ST_ATTACHMENT_BACK_LEFT:
112          att = __DRI_BUFFER_BACK_LEFT;
113          break;
114       case ST_ATTACHMENT_FRONT_RIGHT:
115          att = __DRI_BUFFER_FRONT_RIGHT;
116          break;
117       case ST_ATTACHMENT_BACK_RIGHT:
118          att = __DRI_BUFFER_BACK_RIGHT;
119          break;
120       case ST_ATTACHMENT_DEPTH_STENCIL:
121          att = __DRI_BUFFER_DEPTH_STENCIL;
122          break;
123       default:
124          att = -1;
125          break;
126       }
127
128       bpp = util_format_get_blocksizebits(format);
129
130       if (att >= 0) {
131          attachments[num_attachments++] = att;
132          if (with_format) {
133             attachments[num_attachments++] = bpp;
134          }
135       }
136    }
137
138    if (with_format) {
139       num_attachments /= 2;
140       buffers = loader->getBuffersWithFormat(dri_drawable,
141             &dri_drawable->w, &dri_drawable->h,
142             attachments, num_attachments,
143             &num_buffers, dri_drawable->loaderPrivate);
144    }
145    else {
146       buffers = loader->getBuffers(dri_drawable,
147             &dri_drawable->w, &dri_drawable->h,
148             attachments, num_attachments,
149             &num_buffers, dri_drawable->loaderPrivate);
150    }
151
152    if (buffers) {
153       /* set one cliprect to cover the whole dri_drawable */
154       dri_drawable->x = 0;
155       dri_drawable->y = 0;
156       dri_drawable->backX = 0;
157       dri_drawable->backY = 0;
158       dri_drawable->numClipRects = 1;
159       dri_drawable->pClipRects[0].x1 = 0;
160       dri_drawable->pClipRects[0].y1 = 0;
161       dri_drawable->pClipRects[0].x2 = dri_drawable->w;
162       dri_drawable->pClipRects[0].y2 = dri_drawable->h;
163       dri_drawable->numBackClipRects = 1;
164       dri_drawable->pBackClipRects[0].x1 = 0;
165       dri_drawable->pBackClipRects[0].y1 = 0;
166       dri_drawable->pBackClipRects[0].x2 = dri_drawable->w;
167       dri_drawable->pBackClipRects[0].y2 = dri_drawable->h;
168
169       *count = num_buffers;
170    }
171
172    return buffers;
173 }
174
175 /**
176  * Process __DRIbuffer and convert them into pipe_resources.
177  */
178 static void
179 dri2_drawable_process_buffers(struct dri_drawable *drawable,
180                               __DRIbuffer *buffers, unsigned count)
181 {
182    struct dri_screen *screen = dri_screen(drawable->sPriv);
183    __DRIdrawable *dri_drawable = drawable->dPriv;
184    struct pipe_resource templ;
185    struct winsys_handle whandle;
186    boolean have_depth = FALSE;
187    unsigned i, bind;
188
189    if (drawable->old_num == count &&
190        drawable->old_w == dri_drawable->w &&
191        drawable->old_h == dri_drawable->h &&
192        memcmp(drawable->old, buffers, sizeof(__DRIbuffer) * count) == 0)
193       return;
194
195    for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
196       pipe_resource_reference(&drawable->textures[i], NULL);
197
198    memset(&templ, 0, sizeof(templ));
199    templ.target = screen->target;
200    templ.last_level = 0;
201    templ.width0 = dri_drawable->w;
202    templ.height0 = dri_drawable->h;
203    templ.depth0 = 1;
204    templ.array_size = 1;
205
206    memset(&whandle, 0, sizeof(whandle));
207
208    for (i = 0; i < count; i++) {
209       __DRIbuffer *buf = &buffers[i];
210       enum st_attachment_type statt;
211       enum pipe_format format;
212
213       switch (buf->attachment) {
214       case __DRI_BUFFER_FRONT_LEFT:
215          if (!screen->auto_fake_front) {
216             statt = ST_ATTACHMENT_INVALID;
217             break;
218          }
219          /* fallthrough */
220       case __DRI_BUFFER_FAKE_FRONT_LEFT:
221          statt = ST_ATTACHMENT_FRONT_LEFT;
222          break;
223       case __DRI_BUFFER_BACK_LEFT:
224          statt = ST_ATTACHMENT_BACK_LEFT;
225          break;
226       case __DRI_BUFFER_DEPTH:
227       case __DRI_BUFFER_DEPTH_STENCIL:
228       case __DRI_BUFFER_STENCIL:
229          /* use only the first depth/stencil buffer */
230          if (!have_depth) {
231             have_depth = TRUE;
232             statt = ST_ATTACHMENT_DEPTH_STENCIL;
233          }
234          else {
235             statt = ST_ATTACHMENT_INVALID;
236          }
237          break;
238       default:
239          statt = ST_ATTACHMENT_INVALID;
240          break;
241       }
242
243       dri_drawable_get_format(drawable, statt, &format, &bind);
244       if (statt == ST_ATTACHMENT_INVALID || format == PIPE_FORMAT_NONE)
245          continue;
246
247       templ.format = format;
248       templ.bind = bind;
249       whandle.handle = buf->name;
250       whandle.stride = buf->pitch;
251
252       drawable->textures[statt] =
253          screen->base.screen->resource_from_handle(screen->base.screen,
254                &templ, &whandle);
255    }
256
257    drawable->old_num = count;
258    drawable->old_w = dri_drawable->w;
259    drawable->old_h = dri_drawable->h;
260    memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * count);
261 }
262
263 static __DRIbuffer *
264 dri2_allocate_buffer(__DRIscreen *sPriv,
265                      unsigned attachment, unsigned format,
266                      int width, int height)
267 {
268    struct dri_screen *screen = dri_screen(sPriv);
269    struct dri2_buffer *buffer;
270    struct pipe_resource templ;
271    enum st_attachment_type statt;
272    enum pipe_format pf;
273    unsigned bind = 0;
274    struct winsys_handle whandle;
275
276    switch (attachment) {
277       case __DRI_BUFFER_FRONT_LEFT:
278       case __DRI_BUFFER_FAKE_FRONT_LEFT:
279          statt = ST_ATTACHMENT_FRONT_LEFT;
280          bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
281          break;
282       case __DRI_BUFFER_BACK_LEFT:
283          statt = ST_ATTACHMENT_BACK_LEFT;
284          bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
285          break;
286       case __DRI_BUFFER_DEPTH:
287       case __DRI_BUFFER_DEPTH_STENCIL:
288       case __DRI_BUFFER_STENCIL:
289             statt = ST_ATTACHMENT_DEPTH_STENCIL;
290             bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */
291          break;
292       default:
293          statt = ST_ATTACHMENT_INVALID;
294          break;
295    }
296
297    switch (format) {
298       case 32:
299          pf = PIPE_FORMAT_B8G8R8X8_UNORM;
300          break;
301       case 16:
302          pf = PIPE_FORMAT_Z16_UNORM;
303          break;
304       default:
305          return NULL;
306    }
307
308    buffer = CALLOC_STRUCT(dri2_buffer);
309    if (!buffer)
310       return NULL;
311
312    memset(&templ, 0, sizeof(templ));
313    templ.bind = bind;
314    templ.format = pf;
315    templ.target = PIPE_TEXTURE_2D;
316    templ.last_level = 0;
317    templ.width0 = width;
318    templ.height0 = height;
319    templ.depth0 = 1;
320    templ.array_size = 1;
321
322    buffer->resource =
323       screen->base.screen->resource_create(screen->base.screen, &templ);
324    if (!buffer->resource)
325       return NULL;
326
327    memset(&whandle, 0, sizeof(whandle));
328    whandle.type = DRM_API_HANDLE_TYPE_SHARED;
329    screen->base.screen->resource_get_handle(screen->base.screen,
330          buffer->resource, &whandle);
331
332    buffer->base.attachment = attachment;
333    buffer->base.name = whandle.handle;
334    buffer->base.cpp = util_format_get_blocksize(pf);
335    buffer->base.pitch = whandle.stride;
336
337    return &buffer->base;
338 }
339
340 static void
341 dri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv)
342 {
343    struct dri2_buffer *buffer = dri2_buffer(bPriv);
344
345    pipe_resource_reference(&buffer->resource, NULL);
346    FREE(buffer);
347 }
348
349 /*
350  * Backend functions for st_framebuffer interface.
351  */
352
353 static void
354 dri2_allocate_textures(struct dri_drawable *drawable,
355                        const enum st_attachment_type *statts,
356                        unsigned count)
357 {
358    __DRIbuffer *buffers;
359    unsigned num_buffers = count;
360
361    buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers);
362    if (buffers)
363       dri2_drawable_process_buffers(drawable, buffers, num_buffers);
364 }
365
366 static void
367 dri2_flush_frontbuffer(struct dri_drawable *drawable,
368                        enum st_attachment_type statt)
369 {
370    __DRIdrawable *dri_drawable = drawable->dPriv;
371    struct __DRIdri2LoaderExtensionRec *loader = drawable->sPriv->dri2.loader;
372
373    if (loader->flushFrontBuffer == NULL)
374       return;
375
376    if (statt == ST_ATTACHMENT_FRONT_LEFT) {
377       loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
378    }
379 }
380
381 static __DRIimage *
382 dri2_lookup_egl_image(struct dri_screen *screen, void *handle)
383 {
384    __DRIimageLookupExtension *loader = screen->sPriv->dri2.image;
385    __DRIimage *img;
386
387    if (!loader->lookupEGLImage)
388       return NULL;
389
390    img = loader->lookupEGLImage(screen->sPriv,
391                                 handle, screen->sPriv->loaderPrivate);
392
393    return img;
394 }
395
396 static __DRIimage *
397 dri2_create_image_from_name(__DRIscreen *_screen,
398                             int width, int height, int format,
399                             int name, int pitch, void *loaderPrivate)
400 {
401    struct dri_screen *screen = dri_screen(_screen);
402    __DRIimage *img;
403    struct pipe_resource templ;
404    struct winsys_handle whandle;
405    unsigned tex_usage;
406    enum pipe_format pf;
407
408    tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
409
410    switch (format) {
411    case __DRI_IMAGE_FORMAT_RGB565:
412       pf = PIPE_FORMAT_B5G6R5_UNORM;
413       break;
414    case __DRI_IMAGE_FORMAT_XRGB8888:
415       pf = PIPE_FORMAT_B8G8R8X8_UNORM;
416       break;
417    case __DRI_IMAGE_FORMAT_ARGB8888:
418       pf = PIPE_FORMAT_B8G8R8A8_UNORM;
419       break;
420    default:
421       pf = PIPE_FORMAT_NONE;
422       break;
423    }
424    if (pf == PIPE_FORMAT_NONE)
425       return NULL;
426
427    img = CALLOC_STRUCT(__DRIimageRec);
428    if (!img)
429       return NULL;
430
431    memset(&templ, 0, sizeof(templ));
432    templ.bind = tex_usage;
433    templ.format = pf;
434    templ.target = screen->target;
435    templ.last_level = 0;
436    templ.width0 = width;
437    templ.height0 = height;
438    templ.depth0 = 1;
439    templ.array_size = 1;
440
441    memset(&whandle, 0, sizeof(whandle));
442    whandle.handle = name;
443    whandle.stride = pitch * util_format_get_blocksize(pf);
444
445    img->texture = screen->base.screen->resource_from_handle(screen->base.screen,
446          &templ, &whandle);
447    if (!img->texture) {
448       FREE(img);
449       return NULL;
450    }
451
452    img->level = 0;
453    img->layer = 0;
454    img->loader_private = loaderPrivate;
455
456    return img;
457 }
458
459 static __DRIimage *
460 dri2_create_image_from_renderbuffer(__DRIcontext *context,
461                                     int renderbuffer, void *loaderPrivate)
462 {
463    struct dri_context *ctx = dri_context(context);
464
465    if (!ctx->st->get_resource_for_egl_image)
466       return NULL;
467
468    /* TODO */
469    return NULL;
470 }
471
472 static __DRIimage *
473 dri2_create_image(__DRIscreen *_screen,
474                    int width, int height, int format,
475                    unsigned int use, void *loaderPrivate)
476 {
477    struct dri_screen *screen = dri_screen(_screen);
478    __DRIimage *img;
479    struct pipe_resource templ;
480    unsigned tex_usage;
481    enum pipe_format pf;
482
483    tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
484    if (use & __DRI_IMAGE_USE_SCANOUT)
485       tex_usage |= PIPE_BIND_SCANOUT;
486    if (use & __DRI_IMAGE_USE_SHARE)
487       tex_usage |= PIPE_BIND_SHARED;
488    if (use & __DRI_IMAGE_USE_CURSOR) {
489       if (width != 64 || height != 64)
490          return NULL;
491       tex_usage |= PIPE_BIND_CURSOR;
492    }
493
494    switch (format) {
495    case __DRI_IMAGE_FORMAT_RGB565:
496       pf = PIPE_FORMAT_B5G6R5_UNORM;
497       break;
498    case __DRI_IMAGE_FORMAT_XRGB8888:
499       pf = PIPE_FORMAT_B8G8R8X8_UNORM;
500       break;
501    case __DRI_IMAGE_FORMAT_ARGB8888:
502       pf = PIPE_FORMAT_B8G8R8A8_UNORM;
503       break;
504    default:
505       pf = PIPE_FORMAT_NONE;
506       break;
507    }
508    if (pf == PIPE_FORMAT_NONE)
509       return NULL;
510
511    img = CALLOC_STRUCT(__DRIimageRec);
512    if (!img)
513       return NULL;
514
515    memset(&templ, 0, sizeof(templ));
516    templ.bind = tex_usage;
517    templ.format = pf;
518    templ.target = PIPE_TEXTURE_2D;
519    templ.last_level = 0;
520    templ.width0 = width;
521    templ.height0 = height;
522    templ.depth0 = 1;
523    templ.array_size = 1;
524
525    img->texture = screen->base.screen->resource_create(screen->base.screen, &templ);
526    if (!img->texture) {
527       FREE(img);
528       return NULL;
529    }
530
531    img->level = 0;
532    img->layer = 0;
533
534    img->loader_private = loaderPrivate;
535    return img;
536 }
537
538 static GLboolean
539 dri2_query_image(__DRIimage *image, int attrib, int *value)
540 {
541    struct winsys_handle whandle;
542    memset(&whandle, 0, sizeof(whandle));
543
544    switch (attrib) {
545    case __DRI_IMAGE_ATTRIB_STRIDE:
546       image->texture->screen->resource_get_handle(image->texture->screen,
547             image->texture, &whandle);
548       *value = whandle.stride;
549       return GL_TRUE;
550    case __DRI_IMAGE_ATTRIB_HANDLE:
551       whandle.type = DRM_API_HANDLE_TYPE_KMS;
552       image->texture->screen->resource_get_handle(image->texture->screen,
553          image->texture, &whandle);
554       *value = whandle.handle;
555       return GL_TRUE;
556    case __DRI_IMAGE_ATTRIB_NAME:
557       whandle.type = DRM_API_HANDLE_TYPE_SHARED;
558       image->texture->screen->resource_get_handle(image->texture->screen,
559          image->texture, &whandle);
560       *value = whandle.handle;
561       return GL_TRUE;
562    default:
563       return GL_FALSE;
564    }
565 }
566
567 static __DRIimage *
568 dri2_dup_image(__DRIimage *image, void *loaderPrivate)
569 {
570    __DRIimage *img;
571
572    img = CALLOC_STRUCT(__DRIimageRec);
573    if (!img)
574       return NULL;
575
576    img->texture = NULL;
577    pipe_resource_reference(&img->texture, image->texture);
578    img->level = image->level;
579    img->layer = image->layer;
580    img->loader_private = loaderPrivate;
581
582    return img;
583 }
584
585 static void
586 dri2_destroy_image(__DRIimage *img)
587 {
588    pipe_resource_reference(&img->texture, NULL);
589    FREE(img);
590 }
591
592 static struct __DRIimageExtensionRec dri2ImageExtension = {
593     { __DRI_IMAGE, __DRI_IMAGE_VERSION },
594     dri2_create_image_from_name,
595     dri2_create_image_from_renderbuffer,
596     dri2_destroy_image,
597     dri2_create_image,
598     dri2_query_image,
599     dri2_dup_image,
600 };
601
602 /*
603  * Backend function init_screen.
604  */
605
606 static const __DRIextension *dri_screen_extensions[] = {
607    &driReadDrawableExtension,
608    &driCopySubBufferExtension.base,
609    &driSwapControlExtension.base,
610    &driMediaStreamCounterExtension.base,
611    &driTexBufferExtension.base,
612    &dri2FlushExtension.base,
613    &dri2ImageExtension.base,
614    &dri2ConfigQueryExtension.base,
615    NULL
616 };
617
618 /**
619  * This is the driver specific part of the createNewScreen entry point.
620  *
621  * Returns the struct gl_config supported by this driver.
622  */
623 static const __DRIconfig **
624 dri2_init_screen(__DRIscreen * sPriv)
625 {
626    const __DRIconfig **configs;
627    struct dri_screen *screen;
628    struct pipe_screen *pscreen;
629
630    screen = CALLOC_STRUCT(dri_screen);
631    if (!screen)
632       return NULL;
633
634    screen->sPriv = sPriv;
635    screen->fd = sPriv->fd;
636
637    sPriv->private = (void *)screen;
638    sPriv->extensions = dri_screen_extensions;
639
640    pscreen = driver_descriptor.create_screen(screen->fd);
641    /* dri_init_screen_helper checks pscreen for us */
642
643    configs = dri_init_screen_helper(screen, pscreen, 32);
644    if (!configs)
645       goto fail;
646
647    sPriv->api_mask = 0;
648    if (screen->st_api->profile_mask & ST_PROFILE_DEFAULT_MASK)
649       sPriv->api_mask |= 1 << __DRI_API_OPENGL;
650    if (screen->st_api->profile_mask & ST_PROFILE_OPENGL_ES1_MASK)
651       sPriv->api_mask |= 1 << __DRI_API_GLES;
652    if (screen->st_api->profile_mask & ST_PROFILE_OPENGL_ES2_MASK)
653       sPriv->api_mask |= 1 << __DRI_API_GLES2;
654
655    screen->auto_fake_front = dri_with_format(sPriv);
656    screen->broken_invalidate = !sPriv->dri2.useInvalidate;
657    screen->lookup_egl_image = dri2_lookup_egl_image;
658
659    return configs;
660 fail:
661    dri_destroy_screen_helper(screen);
662    FREE(screen);
663    return NULL;
664 }
665
666 static boolean
667 dri2_create_context(gl_api api, const struct gl_config * visual,
668                     __DRIcontext * cPriv, void *sharedContextPrivate)
669 {
670    struct dri_context *ctx = NULL;
671
672    if (!dri_create_context(api, visual, cPriv, sharedContextPrivate))
673       return FALSE;
674
675    ctx = cPriv->driverPrivate;
676
677    return TRUE;
678 }
679
680 static boolean
681 dri2_create_buffer(__DRIscreen * sPriv,
682                    __DRIdrawable * dPriv,
683                    const struct gl_config * visual, boolean isPixmap)
684 {
685    struct dri_drawable *drawable = NULL;
686
687    if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap))
688       return FALSE;
689
690    drawable = dPriv->driverPrivate;
691
692    drawable->allocate_textures = dri2_allocate_textures;
693    drawable->flush_frontbuffer = dri2_flush_frontbuffer;
694
695    return TRUE;
696 }
697
698 /**
699  * DRI driver virtual function table.
700  *
701  * DRI versions differ in their implementation of init_screen and swap_buffers.
702  */
703 const struct __DriverAPIRec driDriverAPI = {
704    .InitScreen = NULL,
705    .InitScreen2 = dri2_init_screen,
706    .DestroyScreen = dri_destroy_screen,
707    .CreateContext = dri2_create_context,
708    .DestroyContext = dri_destroy_context,
709    .CreateBuffer = dri2_create_buffer,
710    .DestroyBuffer = dri_destroy_buffer,
711    .MakeCurrent = dri_make_current,
712    .UnbindContext = dri_unbind_context,
713
714    .GetSwapInfo = NULL,
715    .GetDrawableMSC = NULL,
716    .WaitForMSC = NULL,
717
718    .SwapBuffers = NULL,
719    .CopySubBuffer = NULL,
720
721    .AllocateBuffer = dri2_allocate_buffer,
722    .ReleaseBuffer  = dri2_release_buffer,
723 };
724
725 /* This is the table of extensions that the loader will dlsym() for. */
726 PUBLIC const __DRIextension *__driDriverExtensions[] = {
727     &driCoreExtension.base,
728     &driLegacyExtension.base,
729     &driDRI2Extension.base,
730     NULL
731 };
732
733 /* vim: set sw=3 ts=8 sts=3 expandtab: */