1
/* $Id: fakedri_drv.c $ */
4
* VBox OpenGL DRI driver functions
8
* Copyright (C) 2009 Oracle Corporation
10
* This file is part of VirtualBox Open Source Edition (OSE), as
11
* available from http://www.virtualbox.org. This file is free software;
12
* you can redistribute it and/or modify it under the terms of the GNU
13
* General Public License (GPL) as published by the Free Software
14
* Foundation, in version 2 as it comes in the "COPYING" file of the
15
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
25
#include "fakedri_drv.h"
34
#define VBOX_NO_MESA_PATCH_REPORTS
36
//#define DEBUG_DRI_CALLS
38
//@todo this could be different...
40
# define DRI_DEFAULT_DRIVER_DIR "/usr/lib64/dri:/usr/lib/dri"
41
# define DRI_XORG_DRV_DIR "/usr/lib/xorg/modules/drivers/"
43
# define DRI_DEFAULT_DRIVER_DIR "/usr/lib/dri"
44
# define DRI_XORG_DRV_DIR "/usr/lib/xorg/modules/drivers/"
47
#ifdef DEBUG_DRI_CALLS
48
#define SWDRI_SHOWNAME(pext, func) \
49
crDebug("SWDRI: sc %s->%s", #pext, #func)
51
#define SWDRI_SHOWNAME(pext, func)
54
#define SWDRI_SAFECALL(pext, func, ...) \
55
SWDRI_SHOWNAME(pext, func); \
56
if (pext && pext->func){ \
57
(*pext->func)(__VA_ARGS__); \
59
crDebug("swcore_call NULL for "#func); \
62
#define SWDRI_SAFERET(pext, func, ...) \
63
SWDRI_SHOWNAME(pext, func); \
64
if (pext && pext->func){ \
65
return (*pext->func)(__VA_ARGS__); \
67
crDebug("swcore_call NULL for "#func); \
71
#define SWDRI_SAFERET_CORE(func, ...) SWDRI_SAFERET(gpSwDriCoreExternsion, func, __VA_ARGS__)
72
#define SWDRI_SAFECALL_CORE(func, ...) SWDRI_SAFECALL(gpSwDriCoreExternsion, func, __VA_ARGS__)
73
#define SWDRI_SAFERET_SWRAST(func, ...) SWDRI_SAFERET(gpSwDriSwrastExtension, func, __VA_ARGS__)
74
#define SWDRI_SAFECALL_SWRAST(func, ...) SWDRI_SAFECALL(gpSwDriSwrastExtension, func, __VA_ARGS__)
81
# define DRI_ELFSYM Elf64_Sym
83
# define DRI_ELFSYM Elf32_Sym
87
typedef struct _FAKEDRI_PatchNode
89
const char* psFuncName;
90
void *pDstStart, *pDstEnd;
91
const void *pSrcStart, *pSrcEnd;
93
struct _FAKEDRI_PatchNode *pNext;
95
static FAKEDRI_PatchNode *g_pFreeList=NULL, *g_pRepatchList=NULL;
98
static struct _glapi_table* vbox_glapi_table = NULL;
99
fakedri_glxapi_table glxim;
101
static const __DRIextension **gppSwDriExternsion = NULL;
102
static const __DRIcoreExtension *gpSwDriCoreExternsion = NULL;
103
static const __DRIswrastExtension *gpSwDriSwrastExtension = NULL;
105
extern const __DRIextension * __driDriverExtensions[];
107
#define VBOX_SET_MESA_FUNC(table, name, func) \
108
if (_glapi_get_proc_offset(name)>=0) SET_by_offset(table, _glapi_get_proc_offset(name), func); \
109
else crWarning("%s not found in mesa table", name)
111
#define GLAPI_ENTRY(Func) VBOX_SET_MESA_FUNC(vbox_glapi_table, "gl"#Func, cr_gl##Func);
114
vboxPatchMesaExport(const char* psFuncName, const void *pStart, const void *pEnd);
117
vboxPatchMesaGLAPITable()
121
pGLTable = (void *)_glapi_get_dispatch();
122
vbox_glapi_table = crAlloc(_glapi_get_dispatch_table_size() * sizeof (void *));
123
if (!vbox_glapi_table)
125
crError("Not enough memory to allocate dispatch table");
127
crMemcpy(vbox_glapi_table, pGLTable, _glapi_get_dispatch_table_size() * sizeof (void *));
129
#include "fakedri_glfuncsList.h"
131
VBOX_SET_MESA_FUNC(vbox_glapi_table, "glBlendEquationSeparateEXT", cr_glBlendEquationSeparate);
132
VBOX_SET_MESA_FUNC(vbox_glapi_table, "glSampleMaskSGIS", cr_glSampleMaskEXT);
133
VBOX_SET_MESA_FUNC(vbox_glapi_table, "glSamplePatternSGIS", cr_glSamplePatternEXT);
134
VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2dMESA", cr_glWindowPos2d);
135
VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2dvMESA", cr_glWindowPos2dv);
136
VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2fMESA", cr_glWindowPos2f);
137
VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2fvMESA", cr_glWindowPos2fv);
138
VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2iMESA", cr_glWindowPos2i);
139
VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2ivMESA", cr_glWindowPos2iv);
140
VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2sMESA", cr_glWindowPos2s);
141
VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2svMESA", cr_glWindowPos2sv);
142
VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3dMESA", cr_glWindowPos3d);
143
VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3dvMESA", cr_glWindowPos3dv);
144
VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3fMESA", cr_glWindowPos3f);
145
VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3fvMESA", cr_glWindowPos3fv);
146
VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3iMESA", cr_glWindowPos3i);
147
VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3ivMESA", cr_glWindowPos3iv);
148
VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3sMESA", cr_glWindowPos3s);
149
VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3svMESA", cr_glWindowPos3sv);
151
_glapi_set_dispatch(vbox_glapi_table);
155
#define GLXAPI_ENTRY(Func) pGLXTable->Func = VBOXGLXTAG(glX##Func);
157
vboxFillGLXAPITable(fakedri_glxapi_table *pGLXTable)
159
#include "fakedri_glxfuncsList.h"
164
vboxApplyPatch(const char* psFuncName, void *pDst, const void *pSrc, unsigned long size)
169
/* Get aligned start address we're going to patch*/
170
alPatch = (void*) ((uintptr_t)pDst & ~(uintptr_t)(PAGESIZE-1));
172
#ifndef VBOX_NO_MESA_PATCH_REPORTS
173
crDebug("MProtecting: %p, %li", alPatch, pDst-alPatch+size);
176
/* Get write access to mesa functions */
177
rv = RTMemProtect(alPatch, pDst-alPatch+size, RTMEM_PROT_READ|RTMEM_PROT_WRITE|RTMEM_PROT_EXEC);
180
crError("mprotect failed with %x (%s)", rv, psFuncName);
183
#ifndef VBOX_NO_MESA_PATCH_REPORTS
184
crDebug("Writing %li bytes to %p from %p", size, pDst, pSrc);
187
crMemcpy(pDst, pSrc, size);
189
/*@todo Restore the protection, probably have to check what was it before us...*/
190
rv = RTMemProtect(alPatch, pDst-alPatch+size, RTMEM_PROT_READ|RTMEM_PROT_EXEC);
193
crError("mprotect2 failed with %x (%s)", rv, psFuncName);
197
#define FAKEDRI_JMP64_PATCH_SIZE 13
200
vboxPatchMesaExport(const char* psFuncName, const void *pStart, const void *pEnd)
207
char patch[FAKEDRI_JMP64_PATCH_SIZE];
209
int ignore_size=false;
211
#ifndef VBOX_NO_MESA_PATCH_REPORTS
212
crDebug("\nvboxPatchMesaExport: %s", psFuncName);
215
pMesaEntry = dlsym(RTLD_DEFAULT, psFuncName);
219
crDebug("%s not defined in current scope, are we being loaded by mesa's libGL.so?", psFuncName);
223
rv = dladdr1(pMesaEntry, &dlip, (void**)&sym, RTLD_DL_SYMENT);
226
crError("Failed to get size for %p(%s)", pMesaEntry, psFuncName);
230
#if VBOX_OGL_GLX_USE_CSTUBS
236
rv = dladdr1(pStart, &dlip1, (void**)&sym1, RTLD_DL_SYMENT);
239
crError("Failed to get size for vbox %p", pStart);
243
pEnd = pStart + sym1->st_size;
244
# ifndef VBOX_NO_MESA_PATCH_REPORTS
245
crDebug("VBox Entry: %p, start: %p(%s:%s), size: %li", pStart, dlip1.dli_saddr, dlip1.dli_fname, dlip1.dli_sname, sym1->st_size);
250
#ifndef VBOX_NO_MESA_PATCH_REPORTS
251
crDebug("Mesa Entry: %p, start: %p(%s:%s), size: %li", pMesaEntry, dlip.dli_saddr, dlip.dli_fname, dlip.dli_sname, sym->st_size);
252
crDebug("Vbox code: start: %p, end %p, size: %li", pStart, pEnd, pEnd-pStart);
255
#ifndef VBOX_OGL_GLX_USE_CSTUBS
256
if (sym->st_size<(pEnd-pStart))
262
/* Try to insert 5 bytes jmp/jmpq to our stub code */
266
/*@todo we don't really know the size of targeted static function, but it's long enough in practice. We will also patch same place twice, but it's ok.*/
267
if (!crStrcmp(psFuncName, "glXDestroyContext") || !crStrcmp(psFuncName, "glXFreeContextEXT"))
269
if (((unsigned char*)dlip.dli_saddr)[0]==0xEB)
271
/*it's a rel8 jmp, so we're going to patch the place it targets instead of jmp itself*/
272
dlip.dli_saddr = (void*) ((intptr_t)dlip.dli_saddr + ((char*)dlip.dli_saddr)[1] + 2);
277
crError("Can't patch size is too small.(%s)", psFuncName);
281
else if (!crStrcmp(psFuncName, "glXCreateGLXPixmapMESA"))
283
/*@todo it's just a return 0, which we're fine with for now*/
288
crError("Can't patch size is too small.(%s)", psFuncName);
293
shift = (void*)((intptr_t)pStart-((intptr_t)dlip.dli_saddr+5));
295
offset = (intptr_t)shift;
296
if (offset>INT32_MAX || offset<INT32_MIN)
298
/*try to insert 64bit abs jmp*/
299
if (sym->st_size>=FAKEDRI_JMP64_PATCH_SIZE || ignore_size)
301
# ifndef VBOX_NO_MESA_PATCH_REPORTS
302
crDebug("Inserting movq/jmp instead");
304
/*add 64bit abs jmp*/
305
patch[0] = 0x49; /*movq %r11,imm64*/
307
crMemcpy(&patch[2], &pStart, 8);
308
patch[10] = 0x41; /*jmp *%r11*/
312
pEnd = &patch[FAKEDRI_JMP64_PATCH_SIZE];
316
FAKEDRI_PatchNode *pNode;
317
# ifndef VBOX_NO_MESA_PATCH_REPORTS
318
crDebug("Can't patch offset is too big. Pushing for 2nd pass(%s)", psFuncName);
320
/*Add patch node to repatch with chain jmps in 2nd pass*/
321
pNode = (FAKEDRI_PatchNode *)crAlloc(sizeof(FAKEDRI_PatchNode));
324
crError("Not enough memory.");
327
pNode->psFuncName = psFuncName;
328
pNode->pDstStart = dlip.dli_saddr;
329
pNode->pDstEnd = dlip.dli_saddr+sym->st_size;
330
pNode->pSrcStart = pStart;
331
pNode->pSrcEnd = pEnd;
332
pNode->pNext = g_pRepatchList;
333
g_pRepatchList = pNode;
340
#ifndef VBOX_NO_MESA_PATCH_REPORTS
341
crDebug("Inserting jmp[q] with shift %p instead", shift);
344
crMemcpy(&patch[1], &shift, 4);
350
vboxApplyPatch(psFuncName, dlip.dli_saddr, pStart, pEnd-pStart);
353
/*Add rest of mesa function body to free list*/
354
if (sym->st_size-(pEnd-pStart)>=FAKEDRI_JMP64_PATCH_SIZE)
356
FAKEDRI_PatchNode *pNode = (FAKEDRI_PatchNode *)crAlloc(sizeof(FAKEDRI_PatchNode));
359
pNode->psFuncName = psFuncName;
360
pNode->pDstStart = dlip.dli_saddr+(pEnd-pStart);
361
pNode->pDstEnd = dlip.dli_saddr+sym->st_size;
362
pNode->pSrcStart = dlip.dli_saddr;
363
pNode->pSrcEnd = NULL;
364
pNode->pNext = g_pFreeList;
366
# ifndef VBOX_NO_MESA_PATCH_REPORTS
367
crDebug("Added free node %s, func start=%p, free start=%p, size=%#lx",
368
psFuncName, pNode->pSrcStart, pNode->pDstStart, pNode->pDstEnd-pNode->pDstStart);
377
vboxRepatchMesaExports(void)
379
FAKEDRI_PatchNode *pFreeNode, *pPatchNode;
381
char patch[FAKEDRI_JMP64_PATCH_SIZE];
383
pPatchNode = g_pRepatchList;
386
# ifndef VBOX_NO_MESA_PATCH_REPORTS
387
crDebug("\nvboxRepatchMesaExports %s", pPatchNode->psFuncName);
389
/*find free place in mesa functions, to place 64bit jump to our stub code*/
390
pFreeNode = g_pFreeList;
393
if (pFreeNode->pDstEnd-pFreeNode->pDstStart>=FAKEDRI_JMP64_PATCH_SIZE)
395
offset = ((intptr_t)pFreeNode->pDstStart-((intptr_t)pPatchNode->pDstStart+5));
396
if (offset<=INT32_MAX && offset>=INT32_MIN)
401
pFreeNode=pFreeNode->pNext;
406
crError("Failed to find free space, to place repatch for %s.", pPatchNode->psFuncName);
410
/*add 32bit rel jmp, from mesa orginal function to free space in other mesa function*/
412
crMemcpy(&patch[1], &offset, 4);
413
# ifndef VBOX_NO_MESA_PATCH_REPORTS
414
crDebug("Adding jmp from mesa %s to mesa %s+%#lx", pPatchNode->psFuncName, pFreeNode->psFuncName,
415
pFreeNode->pDstStart-pFreeNode->pSrcStart);
417
vboxApplyPatch(pPatchNode->psFuncName, pPatchNode->pDstStart, &patch[0], 5);
419
/*add 64bit abs jmp, from free space to our stub code*/
420
patch[0] = 0x49; /*movq %r11,imm64*/
422
crMemcpy(&patch[2], &pPatchNode->pSrcStart, 8);
423
patch[10] = 0x41; /*jmp *%r11*/
426
# ifndef VBOX_NO_MESA_PATCH_REPORTS
427
crDebug("Adding jmp from mesa %s+%#lx to vbox %s", pFreeNode->psFuncName, pFreeNode->pDstStart-pFreeNode->pSrcStart,
428
pPatchNode->psFuncName);
430
vboxApplyPatch(pFreeNode->psFuncName, pFreeNode->pDstStart, &patch[0], FAKEDRI_JMP64_PATCH_SIZE);
431
/*mark this space as used*/
432
pFreeNode->pDstStart = pFreeNode->pDstStart+FAKEDRI_JMP64_PATCH_SIZE;
434
pPatchNode = pPatchNode->pNext;
439
vboxFakeDriFreeList(FAKEDRI_PatchNode *pList)
441
FAKEDRI_PatchNode *pNode;
452
#ifdef VBOX_OGL_GLX_USE_CSTUBS
454
# define GLXAPI_ENTRY(Func) vboxPatchMesaExport("glX"#Func, &vbox_glX##Func, NULL);
455
vboxPatchMesaExports()
458
# define GLXAPI_ENTRY(Func) vboxPatchMesaExport("glX"#Func, &vbox_glX##Func, &vbox_glX##Func##_EndProc);
459
vboxPatchMesaExports()
462
crDebug("Patching mesa glx entries");
463
#include "fakedri_glxfuncsList.h"
466
vboxRepatchMesaExports();
467
vboxFakeDriFreeList(g_pRepatchList);
468
g_pRepatchList = NULL;
469
vboxFakeDriFreeList(g_pFreeList);
475
bool vbox_load_sw_dri()
477
const char *libPaths, *p, *next;;
478
char realDriverName[200];
482
/*code from Mesa-7.2/src/glx/x11/dri_common.c:driOpenDriver*/
485
if (geteuid() == getuid()) {
486
/* don't allow setuid apps to use LIBGL_DRIVERS_PATH */
487
libPaths = getenv("LIBGL_DRIVERS_PATH");
489
libPaths = getenv("LIBGL_DRIVERS_DIR"); /* deprecated */
491
if (libPaths == NULL)
492
libPaths = DRI_DEFAULT_DRIVER_DIR;
495
for (p = libPaths; *p; p = next)
497
next = strchr(p, ':');
509
snprintf(realDriverName, sizeof realDriverName, "%.*s/%s_dri.so", len, p, "swrast");
510
crDebug("trying %s", realDriverName);
511
handle = dlopen(realDriverName, RTLD_NOW | RTLD_LOCAL);
517
if (handle) gppSwDriExternsion = dlsym(handle, "__driDriverExtensions");
519
if (!gppSwDriExternsion)
521
crDebug("%s doesn't export __driDriverExtensions", realDriverName);
524
crDebug("loaded %s", realDriverName);
526
for (i = 0; gppSwDriExternsion[i]; i++)
528
if (strcmp(gppSwDriExternsion[i]->name, __DRI_CORE) == 0)
529
gpSwDriCoreExternsion = (__DRIcoreExtension *) gppSwDriExternsion[i];
530
if (strcmp(gppSwDriExternsion[i]->name, __DRI_SWRAST) == 0)
531
gpSwDriSwrastExtension = (__DRIswrastExtension *) gppSwDriExternsion[i];
534
return gpSwDriCoreExternsion && gpSwDriSwrastExtension;
537
void __attribute__ ((constructor)) vbox_install_into_mesa(void)
540
#ifdef _X_ATTRIBUTE_PRINTF
541
void (*pxf86Msg)(MessageType type, const char *format, ...) _X_ATTRIBUTE_PRINTF(2,3);
543
void (*pxf86Msg)(MessageType type, const char *format, ...) _printf_attribute(2,3);
546
pxf86Msg = dlsym(RTLD_DEFAULT, "xf86Msg");
549
pxf86Msg(X_INFO, "Next line is added to allow vboxvideo_drv.so to appear as whitelisted driver\n");
550
pxf86Msg(X_INFO, "The file referenced, is *NOT* loaded\n");
551
pxf86Msg(X_INFO, "Loading %s/ati_drv.so\n", DRI_XORG_DRV_DIR);
553
/* we're failing to proxy software dri driver calls for certain xservers, so just make sure we're unloaded for now */
554
__driDriverExtensions[0] = NULL;
561
crDebug("vboxdriInitScreen: stubInit failed");
565
/* Load swrast_dri.so to proxy dri related calls there. */
566
if (!vbox_load_sw_dri())
568
crDebug("vboxdriInitScreen: vbox_load_sw_dri failed...going to fail badly");
573
* In the end application call would look like this:
574
* app call glFoo->(mesa asm dispatch stub)->cr_glFoo(vbox asm dispatch stub)->SPU Foo function(packspuFoo or alike)
575
* Note, we don't need to install extension functions via _glapi_add_dispatch, because we'd override glXGetProcAddress.
577
/* Mesa's dispatch table is different across library versions, have to modify mesa's table using offset info functions*/
578
vboxPatchMesaGLAPITable();
581
* In the end application call would look like this:
582
* app call glxFoo->(mesa asm dispatch stub patched with vbox_glXFoo:jmp glxim[Foo's index])->VBOXGLXTAG(glxFoo)
584
/* Fill structure used by our assembly stubs */
585
vboxFillGLXAPITable(&glxim);
586
/* Now patch functions exported by libGL.so */
587
vboxPatchMesaExports();
591
* @todo we're missing first glx related call from the client application.
592
* Luckily, this doesn't add much problems, except for some cases.
595
/* __DRIcoreExtension */
598
vboxdriCreateNewScreen(int screen, int fd, unsigned int sarea_handle,
599
const __DRIextension **extensions, const __DRIconfig ***driverConfigs,
604
SWDRI_SAFERET_SWRAST(createNewScreen, screen, extensions, driverConfigs, loaderPrivate);
608
vboxdriDestroyScreen(__DRIscreen *screen)
610
SWDRI_SAFECALL_CORE(destroyScreen, screen);
613
static const __DRIextension **
614
vboxdriGetExtensions(__DRIscreen *screen)
616
SWDRI_SAFERET_CORE(getExtensions, screen);
620
vboxdriGetConfigAttrib(const __DRIconfig *config,
624
SWDRI_SAFERET_CORE(getConfigAttrib, config, attrib, value);
628
vboxdriIndexConfigAttrib(const __DRIconfig *config, int index,
629
unsigned int *attrib, unsigned int *value)
631
SWDRI_SAFERET_CORE(indexConfigAttrib, config, index, attrib, value);
634
static __DRIdrawable *
635
vboxdriCreateNewDrawable(__DRIscreen *screen,
636
const __DRIconfig *config,
637
unsigned int drawable_id,
643
SWDRI_SAFERET_SWRAST(createNewDrawable, screen, config, loaderPrivate);
647
vboxdriDestroyDrawable(__DRIdrawable *drawable)
649
SWDRI_SAFECALL_CORE(destroyDrawable, drawable);
653
vboxdriSwapBuffers(__DRIdrawable *drawable)
655
SWDRI_SAFECALL_CORE(swapBuffers, drawable);
658
static __DRIcontext *
659
vboxdriCreateNewContext(__DRIscreen *screen,
660
const __DRIconfig *config,
661
__DRIcontext *shared,
664
SWDRI_SAFERET_CORE(createNewContext, screen, config, shared, loaderPrivate);
668
vboxdriCopyContext(__DRIcontext *dest,
672
SWDRI_SAFERET_CORE(copyContext, dest, src, mask);
676
vboxdriDestroyContext(__DRIcontext *context)
678
SWDRI_SAFECALL_CORE(destroyContext, context);
682
vboxdriBindContext(__DRIcontext *ctx,
683
__DRIdrawable *pdraw,
684
__DRIdrawable *pread)
686
SWDRI_SAFERET_CORE(bindContext, ctx, pdraw, pread);
690
vboxdriUnbindContext(__DRIcontext *ctx)
692
SWDRI_SAFERET_CORE(unbindContext, ctx)
695
/* __DRIlegacyExtension */
698
vboxdriCreateNewScreen_Legacy(int scrn,
699
const __DRIversion *ddx_version,
700
const __DRIversion *dri_version,
701
const __DRIversion *drm_version,
702
const __DRIframebuffer *frame_buffer,
703
drmAddress pSAREA, int fd,
704
const __DRIextension **extensions,
705
const __DRIconfig ***driver_modes,
713
SWDRI_SAFERET_SWRAST(createNewScreen, scrn, extensions, driver_modes, loaderPrivate);
716
static __DRIdrawable *
717
vboxdriCreateNewDrawable_Legacy(__DRIscreen *psp, const __DRIconfig *config,
718
drm_drawable_t hwDrawable, int renderType,
719
const int *attrs, void *data)
725
SWDRI_SAFERET_SWRAST(createNewDrawable, psp, config, data);
728
static __DRIcontext *
729
vboxdriCreateNewContext_Legacy(__DRIscreen *psp, const __DRIconfig *config,
730
int render_type, __DRIcontext *shared,
731
drm_context_t hwContext, void *data)
735
return vboxdriCreateNewContext(psp, config, shared, data);
739
static const __DRIlegacyExtension vboxdriLegacyExtension = {
740
{ __DRI_LEGACY, __DRI_LEGACY_VERSION },
741
vboxdriCreateNewScreen_Legacy,
742
vboxdriCreateNewDrawable_Legacy,
743
vboxdriCreateNewContext_Legacy
746
static const __DRIcoreExtension vboxdriCoreExtension = {
747
{ __DRI_CORE, __DRI_CORE_VERSION },
748
vboxdriCreateNewScreen, /* driCreateNewScreen */
749
vboxdriDestroyScreen,
750
vboxdriGetExtensions,
751
vboxdriGetConfigAttrib,
752
vboxdriIndexConfigAttrib,
753
vboxdriCreateNewDrawable, /* driCreateNewDrawable */
754
vboxdriDestroyDrawable,
756
vboxdriCreateNewContext,
758
vboxdriDestroyContext,
763
/* This structure is used by dri_util from mesa, don't rename it! */
764
DECLEXPORT(const __DRIextension *) __driDriverExtensions[] = {
765
&vboxdriLegacyExtension.base,
766
&vboxdriCoreExtension.base,