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