VirtualBox

source: vbox/trunk/src/VBox/Additions/common/crOpenGL/fakedri_drv.c@ 43273

Last change on this file since 43273 was 43273, checked in by vboxsync, 12 years ago

Additions/common/crOpenGL: replace a dependency on X server headers with a (standard) definition.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.8 KB
Line 
1/* $Id: fakedri_drv.c 43273 2012-09-10 19:29:40Z vboxsync $ */
2
3/** @file
4 * VBox OpenGL DRI driver functions
5 */
6
7/*
8 * Copyright (C) 2009 Oracle Corporation
9 *
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.
17 */
18
19#define _GNU_SOURCE 1
20
21#include "cr_error.h"
22#include "cr_gl.h"
23#include "cr_mem.h"
24#include "stub.h"
25#include "fakedri_drv.h"
26#include "dri_glx.h"
27#include "iprt/mem.h"
28#include "iprt/err.h"
29#include <dlfcn.h>
30#include <elf.h>
31#include <unistd.h>
32/** X server message type definitions. */
33typedef enum {
34 X_PROBED, /* Value was probed */
35 X_CONFIG, /* Value was given in the config file */
36 X_DEFAULT, /* Value is a default */
37 X_CMDLINE, /* Value was given on the command line */
38 X_NOTICE, /* Notice */
39 X_ERROR, /* Error message */
40 X_WARNING, /* Warning message */
41 X_INFO, /* Informational message */
42 X_NONE, /* No prefix */
43 X_NOT_IMPLEMENTED, /* Not implemented */
44 X_UNKNOWN = -1 /* unknown -- this must always be last */
45} MessageType;
46
47#define VBOX_NO_MESA_PATCH_REPORTS
48
49//#define DEBUG_DRI_CALLS
50
51//@todo this could be different...
52#ifdef RT_ARCH_AMD64
53# define DRI_DEFAULT_DRIVER_DIR "/usr/lib64/dri:/usr/lib/dri:/usr/lib/x86_64-linux-gnu/dri"
54# define DRI_XORG_DRV_DIR "/usr/lib/xorg/modules/drivers/"
55#else
56# define DRI_DEFAULT_DRIVER_DIR "/usr/lib/dri:/usr/lib/i386-linux-gnu/dri"
57# define DRI_XORG_DRV_DIR "/usr/lib/xorg/modules/drivers/"
58#endif
59
60#ifdef DEBUG_DRI_CALLS
61 #define SWDRI_SHOWNAME(pext, func) \
62 crDebug("SWDRI: sc %s->%s", #pext, #func)
63#else
64 #define SWDRI_SHOWNAME(pext, func)
65#endif
66
67#define SWDRI_SAFECALL(pext, func, ...) \
68 SWDRI_SHOWNAME(pext, func); \
69 if (pext && pext->func){ \
70 (*pext->func)(__VA_ARGS__); \
71 } else { \
72 crDebug("swcore_call NULL for "#func); \
73 }
74
75#define SWDRI_SAFERET(pext, func, ...) \
76 SWDRI_SHOWNAME(pext, func); \
77 if (pext && pext->func){ \
78 return (*pext->func)(__VA_ARGS__); \
79 } else { \
80 crDebug("swcore_call NULL for "#func); \
81 return 0; \
82 }
83
84#define SWDRI_SAFERET_CORE(func, ...) SWDRI_SAFERET(gpSwDriCoreExternsion, func, __VA_ARGS__)
85#define SWDRI_SAFECALL_CORE(func, ...) SWDRI_SAFECALL(gpSwDriCoreExternsion, func, __VA_ARGS__)
86#define SWDRI_SAFERET_SWRAST(func, ...) SWDRI_SAFERET(gpSwDriSwrastExtension, func, __VA_ARGS__)
87#define SWDRI_SAFECALL_SWRAST(func, ...) SWDRI_SAFECALL(gpSwDriSwrastExtension, func, __VA_ARGS__)
88
89#ifndef PAGESIZE
90#define PAGESIZE 4096
91#endif
92
93#ifdef RT_ARCH_AMD64
94# define DRI_ELFSYM Elf64_Sym
95#else
96# define DRI_ELFSYM Elf32_Sym
97#endif
98
99#ifdef RT_ARCH_AMD64
100typedef struct _FAKEDRI_PatchNode
101{
102 const char* psFuncName;
103 void *pDstStart, *pDstEnd;
104 const void *pSrcStart, *pSrcEnd;
105
106 struct _FAKEDRI_PatchNode *pNext;
107} FAKEDRI_PatchNode;
108static FAKEDRI_PatchNode *g_pFreeList=NULL, *g_pRepatchList=NULL;
109#endif
110
111static struct _glapi_table* vbox_glapi_table = NULL;
112fakedri_glxapi_table glxim;
113
114static const __DRIextension **gppSwDriExternsion = NULL;
115static const __DRIcoreExtension *gpSwDriCoreExternsion = NULL;
116static const __DRIswrastExtension *gpSwDriSwrastExtension = NULL;
117
118extern const __DRIextension * __driDriverExtensions[];
119
120#define VBOX_SET_MESA_FUNC(table, name, func) \
121 if (_glapi_get_proc_offset(name)>=0) SET_by_offset(table, _glapi_get_proc_offset(name), func); \
122 else crWarning("%s not found in mesa table", name)
123
124#define GLAPI_ENTRY(Func) VBOX_SET_MESA_FUNC(vbox_glapi_table, "gl"#Func, cr_gl##Func);
125
126static void
127vboxPatchMesaExport(const char* psFuncName, const void *pStart, const void *pEnd);
128
129static void
130vboxPatchMesaGLAPITable()
131{
132 void *pGLTable;
133
134 pGLTable = (void *)_glapi_get_dispatch();
135 vbox_glapi_table = crAlloc(_glapi_get_dispatch_table_size() * sizeof (void *));
136 if (!vbox_glapi_table)
137 {
138 crError("Not enough memory to allocate dispatch table");
139 }
140 crMemcpy(vbox_glapi_table, pGLTable, _glapi_get_dispatch_table_size() * sizeof (void *));
141
142 #include "fakedri_glfuncsList.h"
143
144 VBOX_SET_MESA_FUNC(vbox_glapi_table, "glBlendEquationSeparateEXT", cr_glBlendEquationSeparate);
145 VBOX_SET_MESA_FUNC(vbox_glapi_table, "glSampleMaskSGIS", cr_glSampleMaskEXT);
146 VBOX_SET_MESA_FUNC(vbox_glapi_table, "glSamplePatternSGIS", cr_glSamplePatternEXT);
147 VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2dMESA", cr_glWindowPos2d);
148 VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2dvMESA", cr_glWindowPos2dv);
149 VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2fMESA", cr_glWindowPos2f);
150 VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2fvMESA", cr_glWindowPos2fv);
151 VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2iMESA", cr_glWindowPos2i);
152 VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2ivMESA", cr_glWindowPos2iv);
153 VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2sMESA", cr_glWindowPos2s);
154 VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2svMESA", cr_glWindowPos2sv);
155 VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3dMESA", cr_glWindowPos3d);
156 VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3dvMESA", cr_glWindowPos3dv);
157 VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3fMESA", cr_glWindowPos3f);
158 VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3fvMESA", cr_glWindowPos3fv);
159 VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3iMESA", cr_glWindowPos3i);
160 VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3ivMESA", cr_glWindowPos3iv);
161 VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3sMESA", cr_glWindowPos3s);
162 VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3svMESA", cr_glWindowPos3sv);
163
164 _glapi_set_dispatch(vbox_glapi_table);
165};
166#undef GLAPI_ENTRY
167
168#define GLXAPI_ENTRY(Func) pGLXTable->Func = VBOXGLXTAG(glX##Func);
169static void
170vboxFillGLXAPITable(fakedri_glxapi_table *pGLXTable)
171{
172 #include "fakedri_glxfuncsList.h"
173}
174#undef GLXAPI_ENTRY
175
176static void
177vboxApplyPatch(const char* psFuncName, void *pDst, const void *pSrc, unsigned long size)
178{
179 void *alPatch;
180 int rv;
181
182 /* Get aligned start address we're going to patch*/
183 alPatch = (void*) ((uintptr_t)pDst & ~(uintptr_t)(PAGESIZE-1));
184
185#ifndef VBOX_NO_MESA_PATCH_REPORTS
186 crDebug("MProtecting: %p, %li", alPatch, pDst-alPatch+size);
187#endif
188
189 /* Get write access to mesa functions */
190 rv = RTMemProtect(alPatch, pDst-alPatch+size, RTMEM_PROT_READ|RTMEM_PROT_WRITE|RTMEM_PROT_EXEC);
191 if (RT_FAILURE(rv))
192 {
193 crError("mprotect failed with %x (%s)", rv, psFuncName);
194 }
195
196#ifndef VBOX_NO_MESA_PATCH_REPORTS
197 crDebug("Writing %li bytes to %p from %p", size, pDst, pSrc);
198#endif
199
200 crMemcpy(pDst, pSrc, size);
201
202 /*@todo Restore the protection, probably have to check what was it before us...*/
203 rv = RTMemProtect(alPatch, pDst-alPatch+size, RTMEM_PROT_READ|RTMEM_PROT_EXEC);
204 if (RT_FAILURE(rv))
205 {
206 crError("mprotect2 failed with %x (%s)", rv, psFuncName);
207 }
208}
209
210#define FAKEDRI_JMP64_PATCH_SIZE 13
211
212static void
213vboxPatchMesaExport(const char* psFuncName, const void *pStart, const void *pEnd)
214{
215 Dl_info dlip;
216 DRI_ELFSYM* sym=0;
217 int rv;
218 void *alPatch;
219 void *pMesaEntry;
220 char patch[FAKEDRI_JMP64_PATCH_SIZE];
221 void *shift;
222 int ignore_size=false;
223
224#ifndef VBOX_NO_MESA_PATCH_REPORTS
225 crDebug("\nvboxPatchMesaExport: %s", psFuncName);
226#endif
227
228 pMesaEntry = dlsym(RTLD_DEFAULT, psFuncName);
229
230 if (!pMesaEntry)
231 {
232 crDebug("%s not defined in current scope, are we being loaded by mesa's libGL.so?", psFuncName);
233 return;
234 }
235
236 rv = dladdr1(pMesaEntry, &dlip, (void**)&sym, RTLD_DL_SYMENT);
237 if (!rv || !sym)
238 {
239 crError("Failed to get size for %p(%s)", pMesaEntry, psFuncName);
240 return;
241 }
242
243#if VBOX_OGL_GLX_USE_CSTUBS
244 {
245 Dl_info dlip1;
246 DRI_ELFSYM* sym1=0;
247 int rv;
248
249 rv = dladdr1(pStart, &dlip1, (void**)&sym1, RTLD_DL_SYMENT);
250 if (!rv || !sym1)
251 {
252 crError("Failed to get size for vbox %p", pStart);
253 return;
254 }
255
256 pEnd = pStart + sym1->st_size;
257# ifndef VBOX_NO_MESA_PATCH_REPORTS
258 crDebug("VBox Entry: %p, start: %p(%s:%s), size: %li", pStart, dlip1.dli_saddr, dlip1.dli_fname, dlip1.dli_sname, sym1->st_size);
259# endif
260 }
261#endif
262
263#ifndef VBOX_NO_MESA_PATCH_REPORTS
264 crDebug("Mesa Entry: %p, start: %p(%s:%s), size: %li", pMesaEntry, dlip.dli_saddr, dlip.dli_fname, dlip.dli_sname, sym->st_size);
265 crDebug("Vbox code: start: %p, end %p, size: %li", pStart, pEnd, pEnd-pStart);
266#endif
267
268#ifndef VBOX_OGL_GLX_USE_CSTUBS
269 if (sym->st_size<(pEnd-pStart))
270#endif
271 {
272#ifdef RT_ARCH_AMD64
273 int64_t offset;
274#endif
275 /* Try to insert 5 bytes jmp/jmpq to our stub code */
276
277 if (sym->st_size<5)
278 {
279 /*@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.*/
280 if (!crStrcmp(psFuncName, "glXDestroyContext") || !crStrcmp(psFuncName, "glXFreeContextEXT"))
281 {
282 if (((unsigned char*)dlip.dli_saddr)[0]==0xEB)
283 {
284 /*it's a rel8 jmp, so we're going to patch the place it targets instead of jmp itself*/
285 dlip.dli_saddr = (void*) ((intptr_t)dlip.dli_saddr + ((char*)dlip.dli_saddr)[1] + 2);
286 ignore_size = true;
287 }
288 else
289 {
290 crError("Can't patch size is too small.(%s)", psFuncName);
291 return;
292 }
293 }
294 else if (!crStrcmp(psFuncName, "glXCreateGLXPixmapMESA"))
295 {
296 /*@todo it's just a return 0, which we're fine with for now*/
297 return;
298 }
299 else
300 {
301 crError("Can't patch size is too small.(%s)", psFuncName);
302 return;
303 }
304 }
305
306 shift = (void*)((intptr_t)pStart-((intptr_t)dlip.dli_saddr+5));
307#ifdef RT_ARCH_AMD64
308 offset = (intptr_t)shift;
309 if (offset>INT32_MAX || offset<INT32_MIN)
310 {
311 /*try to insert 64bit abs jmp*/
312 if (sym->st_size>=FAKEDRI_JMP64_PATCH_SIZE || ignore_size)
313 {
314# ifndef VBOX_NO_MESA_PATCH_REPORTS
315 crDebug("Inserting movq/jmp instead");
316# endif
317 /*add 64bit abs jmp*/
318 patch[0] = 0x49; /*movq %r11,imm64*/
319 patch[1] = 0xBB;
320 crMemcpy(&patch[2], &pStart, 8);
321 patch[10] = 0x41; /*jmp *%r11*/
322 patch[11] = 0xFF;
323 patch[12] = 0xE3;
324 pStart = &patch[0];
325 pEnd = &patch[FAKEDRI_JMP64_PATCH_SIZE];
326 }
327 else
328 {
329 FAKEDRI_PatchNode *pNode;
330# ifndef VBOX_NO_MESA_PATCH_REPORTS
331 crDebug("Can't patch offset is too big. Pushing for 2nd pass(%s)", psFuncName);
332# endif
333 /*Add patch node to repatch with chain jmps in 2nd pass*/
334 pNode = (FAKEDRI_PatchNode *)crAlloc(sizeof(FAKEDRI_PatchNode));
335 if (!pNode)
336 {
337 crError("Not enough memory.");
338 return;
339 }
340 pNode->psFuncName = psFuncName;
341 pNode->pDstStart = dlip.dli_saddr;
342 pNode->pDstEnd = dlip.dli_saddr+sym->st_size;
343 pNode->pSrcStart = pStart;
344 pNode->pSrcEnd = pEnd;
345 pNode->pNext = g_pRepatchList;
346 g_pRepatchList = pNode;
347 return;
348 }
349 }
350 else
351#endif
352 {
353#ifndef VBOX_NO_MESA_PATCH_REPORTS
354 crDebug("Inserting jmp[q] with shift %p instead", shift);
355#endif
356 patch[0] = 0xE9;
357 crMemcpy(&patch[1], &shift, 4);
358 pStart = &patch[0];
359 pEnd = &patch[5];
360 }
361 }
362
363 vboxApplyPatch(psFuncName, dlip.dli_saddr, pStart, pEnd-pStart);
364
365#ifdef RT_ARCH_AMD64
366 /*Add rest of mesa function body to free list*/
367 if (sym->st_size-(pEnd-pStart)>=FAKEDRI_JMP64_PATCH_SIZE)
368 {
369 FAKEDRI_PatchNode *pNode = (FAKEDRI_PatchNode *)crAlloc(sizeof(FAKEDRI_PatchNode));
370 if (pNode)
371 {
372 pNode->psFuncName = psFuncName;
373 pNode->pDstStart = dlip.dli_saddr+(pEnd-pStart);
374 pNode->pDstEnd = dlip.dli_saddr+sym->st_size;
375 pNode->pSrcStart = dlip.dli_saddr;
376 pNode->pSrcEnd = NULL;
377 pNode->pNext = g_pFreeList;
378 g_pFreeList = pNode;
379# ifndef VBOX_NO_MESA_PATCH_REPORTS
380 crDebug("Added free node %s, func start=%p, free start=%p, size=%#lx",
381 psFuncName, pNode->pSrcStart, pNode->pDstStart, pNode->pDstEnd-pNode->pDstStart);
382# endif
383 }
384 }
385#endif
386}
387
388#ifdef RT_ARCH_AMD64
389static void
390vboxRepatchMesaExports(void)
391{
392 FAKEDRI_PatchNode *pFreeNode, *pPatchNode;
393 int64_t offset;
394 char patch[FAKEDRI_JMP64_PATCH_SIZE];
395
396 pPatchNode = g_pRepatchList;
397 while (pPatchNode)
398 {
399# ifndef VBOX_NO_MESA_PATCH_REPORTS
400 crDebug("\nvboxRepatchMesaExports %s", pPatchNode->psFuncName);
401# endif
402 /*find free place in mesa functions, to place 64bit jump to our stub code*/
403 pFreeNode = g_pFreeList;
404 while (pFreeNode)
405 {
406 if (pFreeNode->pDstEnd-pFreeNode->pDstStart>=FAKEDRI_JMP64_PATCH_SIZE)
407 {
408 offset = ((intptr_t)pFreeNode->pDstStart-((intptr_t)pPatchNode->pDstStart+5));
409 if (offset<=INT32_MAX && offset>=INT32_MIN)
410 {
411 break;
412 }
413 }
414 pFreeNode=pFreeNode->pNext;
415 }
416
417 if (!pFreeNode)
418 {
419 crError("Failed to find free space, to place repatch for %s.", pPatchNode->psFuncName);
420 return;
421 }
422
423 /*add 32bit rel jmp, from mesa orginal function to free space in other mesa function*/
424 patch[0] = 0xE9;
425 crMemcpy(&patch[1], &offset, 4);
426# ifndef VBOX_NO_MESA_PATCH_REPORTS
427 crDebug("Adding jmp from mesa %s to mesa %s+%#lx", pPatchNode->psFuncName, pFreeNode->psFuncName,
428 pFreeNode->pDstStart-pFreeNode->pSrcStart);
429# endif
430 vboxApplyPatch(pPatchNode->psFuncName, pPatchNode->pDstStart, &patch[0], 5);
431
432 /*add 64bit abs jmp, from free space to our stub code*/
433 patch[0] = 0x49; /*movq %r11,imm64*/
434 patch[1] = 0xBB;
435 crMemcpy(&patch[2], &pPatchNode->pSrcStart, 8);
436 patch[10] = 0x41; /*jmp *%r11*/
437 patch[11] = 0xFF;
438 patch[12] = 0xE3;
439# ifndef VBOX_NO_MESA_PATCH_REPORTS
440 crDebug("Adding jmp from mesa %s+%#lx to vbox %s", pFreeNode->psFuncName, pFreeNode->pDstStart-pFreeNode->pSrcStart,
441 pPatchNode->psFuncName);
442# endif
443 vboxApplyPatch(pFreeNode->psFuncName, pFreeNode->pDstStart, &patch[0], FAKEDRI_JMP64_PATCH_SIZE);
444 /*mark this space as used*/
445 pFreeNode->pDstStart = pFreeNode->pDstStart+FAKEDRI_JMP64_PATCH_SIZE;
446
447 pPatchNode = pPatchNode->pNext;
448 }
449}
450
451static void
452vboxFakeDriFreeList(FAKEDRI_PatchNode *pList)
453{
454 FAKEDRI_PatchNode *pNode;
455
456 while (pList)
457 {
458 pNode=pList;
459 pList=pNode->pNext;
460 crFree(pNode);
461 }
462}
463#endif
464
465#ifdef VBOX_OGL_GLX_USE_CSTUBS
466static void
467# define GLXAPI_ENTRY(Func) vboxPatchMesaExport("glX"#Func, &vbox_glX##Func, NULL);
468vboxPatchMesaExports()
469#else
470static void
471# define GLXAPI_ENTRY(Func) vboxPatchMesaExport("glX"#Func, &vbox_glX##Func, &vbox_glX##Func##_EndProc);
472vboxPatchMesaExports()
473#endif
474{
475 crDebug("Patching mesa glx entries");
476 #include "fakedri_glxfuncsList.h"
477
478#ifdef RT_ARCH_AMD64
479 vboxRepatchMesaExports();
480 vboxFakeDriFreeList(g_pRepatchList);
481 g_pRepatchList = NULL;
482 vboxFakeDriFreeList(g_pFreeList);
483 g_pFreeList = NULL;
484#endif
485}
486#undef GLXAPI_ENTRY
487
488bool vbox_load_sw_dri()
489{
490 const char *libPaths, *p, *next;;
491 char realDriverName[200];
492 void *handle;
493 int len, i;
494
495 /*code from Mesa-7.2/src/glx/x11/dri_common.c:driOpenDriver*/
496
497 libPaths = NULL;
498 if (geteuid() == getuid()) {
499 /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */
500 libPaths = getenv("LIBGL_DRIVERS_PATH");
501 if (!libPaths)
502 libPaths = getenv("LIBGL_DRIVERS_DIR"); /* deprecated */
503 }
504 if (libPaths == NULL)
505 libPaths = DRI_DEFAULT_DRIVER_DIR;
506
507 handle = NULL;
508 for (p = libPaths; *p; p = next)
509 {
510 next = strchr(p, ':');
511 if (next == NULL)
512 {
513 len = strlen(p);
514 next = p + len;
515 }
516 else
517 {
518 len = next - p;
519 next++;
520 }
521
522 snprintf(realDriverName, sizeof realDriverName, "%.*s/%s_dri.so", len, p, "swrast");
523 crDebug("trying %s", realDriverName);
524 handle = dlopen(realDriverName, RTLD_NOW | RTLD_LOCAL);
525 if (handle) break;
526 }
527
528 /*end code*/
529
530 if (handle) gppSwDriExternsion = dlsym(handle, "__driDriverExtensions");
531
532 if (!gppSwDriExternsion)
533 {
534 crDebug("%s doesn't export __driDriverExtensions", realDriverName);
535 return false;
536 }
537 crDebug("loaded %s", realDriverName);
538
539 for (i = 0; gppSwDriExternsion[i]; i++)
540 {
541 if (strcmp(gppSwDriExternsion[i]->name, __DRI_CORE) == 0)
542 gpSwDriCoreExternsion = (__DRIcoreExtension *) gppSwDriExternsion[i];
543 if (strcmp(gppSwDriExternsion[i]->name, __DRI_SWRAST) == 0)
544 gpSwDriSwrastExtension = (__DRIswrastExtension *) gppSwDriExternsion[i];
545 }
546
547 return gpSwDriCoreExternsion && gpSwDriSwrastExtension;
548}
549
550void __attribute__ ((constructor)) vbox_install_into_mesa(void)
551{
552 {
553#ifdef _X_ATTRIBUTE_PRINTF
554 void (*pxf86Msg)(MessageType type, const char *format, ...) _X_ATTRIBUTE_PRINTF(2,3);
555#else
556 void (*pxf86Msg)(MessageType type, const char *format, ...) _printf_attribute(2,3);
557#endif
558
559 pxf86Msg = dlsym(RTLD_DEFAULT, "xf86Msg");
560 if (pxf86Msg)
561 {
562 pxf86Msg(X_INFO, "Next line is added to allow vboxvideo_drv.so to appear as whitelisted driver\n");
563 pxf86Msg(X_INFO, "The file referenced, is *NOT* loaded\n");
564 pxf86Msg(X_INFO, "Loading %s/ati_drv.so\n", DRI_XORG_DRV_DIR);
565
566 /* we're failing to proxy software dri driver calls for certain xservers, so just make sure we're unloaded for now */
567 __driDriverExtensions[0] = NULL;
568 return;
569 }
570 }
571
572 if (!stubInit())
573 {
574 crDebug("vboxdriInitScreen: stubInit failed");
575 return;
576 }
577
578 /* Load swrast_dri.so to proxy dri related calls there. */
579 if (!vbox_load_sw_dri())
580 {
581 crDebug("vboxdriInitScreen: vbox_load_sw_dri failed...going to fail badly");
582 return;
583 }
584
585 /* Handle gl api.
586 * In the end application call would look like this:
587 * app call glFoo->(mesa asm dispatch stub)->cr_glFoo(vbox asm dispatch stub)->SPU Foo function(packspuFoo or alike)
588 * Note, we don't need to install extension functions via _glapi_add_dispatch, because we'd override glXGetProcAddress.
589 */
590 /* Mesa's dispatch table is different across library versions, have to modify mesa's table using offset info functions*/
591 vboxPatchMesaGLAPITable();
592
593 /* Handle glx api.
594 * In the end application call would look like this:
595 * app call glxFoo->(mesa asm dispatch stub patched with vbox_glXFoo:jmp glxim[Foo's index])->VBOXGLXTAG(glxFoo)
596 */
597 /* Fill structure used by our assembly stubs */
598 vboxFillGLXAPITable(&glxim);
599 /* Now patch functions exported by libGL.so */
600 vboxPatchMesaExports();
601}
602
603/*
604 * @todo we're missing first glx related call from the client application.
605 * Luckily, this doesn't add much problems, except for some cases.
606 */
607
608/* __DRIcoreExtension */
609
610static __DRIscreen *
611vboxdriCreateNewScreen(int screen, int fd, unsigned int sarea_handle,
612 const __DRIextension **extensions, const __DRIconfig ***driverConfigs,
613 void *loaderPrivate)
614{
615 (void) fd;
616 (void) sarea_handle;
617 SWDRI_SAFERET_SWRAST(createNewScreen, screen, extensions, driverConfigs, loaderPrivate);
618}
619
620static void
621vboxdriDestroyScreen(__DRIscreen *screen)
622{
623 SWDRI_SAFECALL_CORE(destroyScreen, screen);
624}
625
626static const __DRIextension **
627vboxdriGetExtensions(__DRIscreen *screen)
628{
629 SWDRI_SAFERET_CORE(getExtensions, screen);
630}
631
632static int
633vboxdriGetConfigAttrib(const __DRIconfig *config,
634 unsigned int attrib,
635 unsigned int *value)
636{
637 SWDRI_SAFERET_CORE(getConfigAttrib, config, attrib, value);
638}
639
640static int
641vboxdriIndexConfigAttrib(const __DRIconfig *config, int index,
642 unsigned int *attrib, unsigned int *value)
643{
644 SWDRI_SAFERET_CORE(indexConfigAttrib, config, index, attrib, value);
645}
646
647static __DRIdrawable *
648vboxdriCreateNewDrawable(__DRIscreen *screen,
649 const __DRIconfig *config,
650 unsigned int drawable_id,
651 unsigned int head,
652 void *loaderPrivate)
653{
654 (void) drawable_id;
655 (void) head;
656 SWDRI_SAFERET_SWRAST(createNewDrawable, screen, config, loaderPrivate);
657}
658
659static void
660vboxdriDestroyDrawable(__DRIdrawable *drawable)
661{
662 SWDRI_SAFECALL_CORE(destroyDrawable, drawable);
663}
664
665static void
666vboxdriSwapBuffers(__DRIdrawable *drawable)
667{
668 SWDRI_SAFECALL_CORE(swapBuffers, drawable);
669}
670
671static __DRIcontext *
672vboxdriCreateNewContext(__DRIscreen *screen,
673 const __DRIconfig *config,
674 __DRIcontext *shared,
675 void *loaderPrivate)
676{
677 SWDRI_SAFERET_CORE(createNewContext, screen, config, shared, loaderPrivate);
678}
679
680static int
681vboxdriCopyContext(__DRIcontext *dest,
682 __DRIcontext *src,
683 unsigned long mask)
684{
685 SWDRI_SAFERET_CORE(copyContext, dest, src, mask);
686}
687
688static void
689vboxdriDestroyContext(__DRIcontext *context)
690{
691 SWDRI_SAFECALL_CORE(destroyContext, context);
692}
693
694static int
695vboxdriBindContext(__DRIcontext *ctx,
696 __DRIdrawable *pdraw,
697 __DRIdrawable *pread)
698{
699 SWDRI_SAFERET_CORE(bindContext, ctx, pdraw, pread);
700}
701
702static int
703vboxdriUnbindContext(__DRIcontext *ctx)
704{
705 SWDRI_SAFERET_CORE(unbindContext, ctx)
706}
707
708/* __DRIlegacyExtension */
709
710static __DRIscreen *
711vboxdriCreateNewScreen_Legacy(int scrn,
712 const __DRIversion *ddx_version,
713 const __DRIversion *dri_version,
714 const __DRIversion *drm_version,
715 const __DRIframebuffer *frame_buffer,
716 drmAddress pSAREA, int fd,
717 const __DRIextension **extensions,
718 const __DRIconfig ***driver_modes,
719 void *loaderPrivate)
720{
721 (void) ddx_version;
722 (void) dri_version;
723 (void) frame_buffer;
724 (void) pSAREA;
725 (void) fd;
726 SWDRI_SAFERET_SWRAST(createNewScreen, scrn, extensions, driver_modes, loaderPrivate);
727}
728
729static __DRIdrawable *
730vboxdriCreateNewDrawable_Legacy(__DRIscreen *psp, const __DRIconfig *config,
731 drm_drawable_t hwDrawable, int renderType,
732 const int *attrs, void *data)
733{
734 (void) hwDrawable;
735 (void) renderType;
736 (void) attrs;
737 (void) data;
738 SWDRI_SAFERET_SWRAST(createNewDrawable, psp, config, data);
739}
740
741static __DRIcontext *
742vboxdriCreateNewContext_Legacy(__DRIscreen *psp, const __DRIconfig *config,
743 int render_type, __DRIcontext *shared,
744 drm_context_t hwContext, void *data)
745{
746 (void) render_type;
747 (void) hwContext;
748 return vboxdriCreateNewContext(psp, config, shared, data);
749}
750
751
752static const __DRIlegacyExtension vboxdriLegacyExtension = {
753 { __DRI_LEGACY, __DRI_LEGACY_VERSION },
754 vboxdriCreateNewScreen_Legacy,
755 vboxdriCreateNewDrawable_Legacy,
756 vboxdriCreateNewContext_Legacy
757};
758
759static const __DRIcoreExtension vboxdriCoreExtension = {
760 { __DRI_CORE, __DRI_CORE_VERSION },
761 vboxdriCreateNewScreen, /* driCreateNewScreen */
762 vboxdriDestroyScreen,
763 vboxdriGetExtensions,
764 vboxdriGetConfigAttrib,
765 vboxdriIndexConfigAttrib,
766 vboxdriCreateNewDrawable, /* driCreateNewDrawable */
767 vboxdriDestroyDrawable,
768 vboxdriSwapBuffers,
769 vboxdriCreateNewContext,
770 vboxdriCopyContext,
771 vboxdriDestroyContext,
772 vboxdriBindContext,
773 vboxdriUnbindContext
774};
775
776/* This structure is used by dri_util from mesa, don't rename it! */
777DECLEXPORT(const __DRIextension *) __driDriverExtensions[] = {
778 &vboxdriLegacyExtension.base,
779 &vboxdriCoreExtension.base,
780 NULL
781};
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette