VirtualBox

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

Last change on this file since 35263 was 35263, checked in by vboxsync, 13 years ago

crOpenGL: fix crashes in libnux-0.9 gpu tests

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.2 KB
Line 
1/* $Id: fakedri_drv.c 35263 2010-12-20 18:12:36Z 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#include "xf86.h"
33
34#define VBOX_NO_MESA_PATCH_REPORTS
35
36//#define DEBUG_DRI_CALLS
37
38//@todo this could be different...
39#ifdef RT_ARCH_AMD64
40# define DRI_DEFAULT_DRIVER_DIR "/usr/lib64/dri:/usr/lib/dri"
41# define DRI_XORG_DRV_DIR "/usr/lib/xorg/modules/drivers/"
42#else
43# define DRI_DEFAULT_DRIVER_DIR "/usr/lib/dri"
44# define DRI_XORG_DRV_DIR "/usr/lib/xorg/modules/drivers/"
45#endif
46
47#ifdef DEBUG_DRI_CALLS
48 #define SWDRI_SHOWNAME(pext, func) \
49 crDebug("SWDRI: sc %s->%s", #pext, #func)
50#else
51 #define SWDRI_SHOWNAME(pext, func)
52#endif
53
54#define SWDRI_SAFECALL(pext, func, ...) \
55 SWDRI_SHOWNAME(pext, func); \
56 if (pext && pext->func){ \
57 (*pext->func)(__VA_ARGS__); \
58 } else { \
59 crDebug("swcore_call NULL for "#func); \
60 }
61
62#define SWDRI_SAFERET(pext, func, ...) \
63 SWDRI_SHOWNAME(pext, func); \
64 if (pext && pext->func){ \
65 return (*pext->func)(__VA_ARGS__); \
66 } else { \
67 crDebug("swcore_call NULL for "#func); \
68 return 0; \
69 }
70
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__)
75
76#ifndef PAGESIZE
77#define PAGESIZE 4096
78#endif
79
80#ifdef RT_ARCH_AMD64
81# define DRI_ELFSYM Elf64_Sym
82#else
83# define DRI_ELFSYM Elf32_Sym
84#endif
85
86#ifdef RT_ARCH_AMD64
87typedef struct _FAKEDRI_PatchNode
88{
89 const char* psFuncName;
90 void *pDstStart, *pDstEnd;
91 const void *pSrcStart, *pSrcEnd;
92
93 struct _FAKEDRI_PatchNode *pNext;
94} FAKEDRI_PatchNode;
95static FAKEDRI_PatchNode *g_pFreeList=NULL, *g_pRepatchList=NULL;
96#endif
97
98static struct _glapi_table* vbox_glapi_table = NULL;
99fakedri_glxapi_table glxim;
100
101static const __DRIextension **gppSwDriExternsion = NULL;
102static const __DRIcoreExtension *gpSwDriCoreExternsion = NULL;
103static const __DRIswrastExtension *gpSwDriSwrastExtension = NULL;
104
105extern const __DRIextension * __driDriverExtensions[];
106
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)
110
111#define GLAPI_ENTRY(Func) VBOX_SET_MESA_FUNC(vbox_glapi_table, "gl"#Func, cr_gl##Func);
112
113static void
114vboxPatchMesaExport(const char* psFuncName, const void *pStart, const void *pEnd);
115
116static void
117vboxPatchMesaGLAPITable()
118{
119 void *pGLTable;
120
121 pGLTable = (void *)_glapi_get_dispatch();
122 vbox_glapi_table = crAlloc(_glapi_get_dispatch_table_size() * sizeof (void *));
123 if (!vbox_glapi_table)
124 {
125 crError("Not enough memory to allocate dispatch table");
126 }
127 crMemcpy(vbox_glapi_table, pGLTable, _glapi_get_dispatch_table_size() * sizeof (void *));
128
129 #include "fakedri_glfuncsList.h"
130
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);
150
151 _glapi_set_dispatch(vbox_glapi_table);
152};
153#undef GLAPI_ENTRY
154
155#define GLXAPI_ENTRY(Func) pGLXTable->Func = VBOXGLXTAG(glX##Func);
156static void
157vboxFillGLXAPITable(fakedri_glxapi_table *pGLXTable)
158{
159 #include "fakedri_glxfuncsList.h"
160}
161#undef GLXAPI_ENTRY
162
163static void
164vboxApplyPatch(const char* psFuncName, void *pDst, const void *pSrc, unsigned long size)
165{
166 void *alPatch;
167 int rv;
168
169 /* Get aligned start address we're going to patch*/
170 alPatch = (void*) ((uintptr_t)pDst & ~(uintptr_t)(PAGESIZE-1));
171
172#ifndef VBOX_NO_MESA_PATCH_REPORTS
173 crDebug("MProtecting: %p, %li", alPatch, pDst-alPatch+size);
174#endif
175
176 /* Get write access to mesa functions */
177 rv = RTMemProtect(alPatch, pDst-alPatch+size, RTMEM_PROT_READ|RTMEM_PROT_WRITE|RTMEM_PROT_EXEC);
178 if (RT_FAILURE(rv))
179 {
180 crError("mprotect failed with %x (%s)", rv, psFuncName);
181 }
182
183#ifndef VBOX_NO_MESA_PATCH_REPORTS
184 crDebug("Writing %li bytes to %p from %p", size, pDst, pSrc);
185#endif
186
187 crMemcpy(pDst, pSrc, size);
188
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);
191 if (RT_FAILURE(rv))
192 {
193 crError("mprotect2 failed with %x (%s)", rv, psFuncName);
194 }
195}
196
197#define FAKEDRI_JMP64_PATCH_SIZE 13
198
199static void
200vboxPatchMesaExport(const char* psFuncName, const void *pStart, const void *pEnd)
201{
202 Dl_info dlip;
203 DRI_ELFSYM* sym=0;
204 int rv;
205 void *alPatch;
206 void *pMesaEntry;
207 char patch[FAKEDRI_JMP64_PATCH_SIZE];
208 void *shift;
209 int ignore_size=false;
210
211#ifndef VBOX_NO_MESA_PATCH_REPORTS
212 crDebug("\nvboxPatchMesaExport: %s", psFuncName);
213#endif
214
215 pMesaEntry = dlsym(RTLD_DEFAULT, psFuncName);
216
217 if (!pMesaEntry)
218 {
219 crDebug("%s not defined in current scope, are we being loaded by mesa's libGL.so?", psFuncName);
220 return;
221 }
222
223 rv = dladdr1(pMesaEntry, &dlip, (void**)&sym, RTLD_DL_SYMENT);
224 if (!rv || !sym)
225 {
226 crError("Failed to get size for %p(%s)", pMesaEntry, psFuncName);
227 return;
228 }
229
230#if VBOX_OGL_GLX_USE_CSTUBS
231 {
232 Dl_info dlip1;
233 DRI_ELFSYM* sym1=0;
234 int rv;
235
236 rv = dladdr1(pStart, &dlip1, (void**)&sym1, RTLD_DL_SYMENT);
237 if (!rv || !sym1)
238 {
239 crError("Failed to get size for vbox %p", pStart);
240 return;
241 }
242
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);
246# endif
247 }
248#endif
249
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);
253#endif
254
255#ifndef VBOX_OGL_GLX_USE_CSTUBS
256 if (sym->st_size<(pEnd-pStart))
257#endif
258 {
259#ifdef RT_ARCH_AMD64
260 int64_t offset;
261#endif
262 /* Try to insert 5 bytes jmp/jmpq to our stub code */
263
264 if (sym->st_size<5)
265 {
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"))
268 {
269 if (((unsigned char*)dlip.dli_saddr)[0]==0xEB)
270 {
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);
273 ignore_size = true;
274 }
275 else
276 {
277 crError("Can't patch size is too small.(%s)", psFuncName);
278 return;
279 }
280 }
281 else if (!crStrcmp(psFuncName, "glXCreateGLXPixmapMESA"))
282 {
283 /*@todo it's just a return 0, which we're fine with for now*/
284 return;
285 }
286 else
287 {
288 crError("Can't patch size is too small.(%s)", psFuncName);
289 return;
290 }
291 }
292
293 shift = (void*)((intptr_t)pStart-((intptr_t)dlip.dli_saddr+5));
294#ifdef RT_ARCH_AMD64
295 offset = (intptr_t)shift;
296 if (offset>INT32_MAX || offset<INT32_MIN)
297 {
298 /*try to insert 64bit abs jmp*/
299 if (sym->st_size>=FAKEDRI_JMP64_PATCH_SIZE || ignore_size)
300 {
301# ifndef VBOX_NO_MESA_PATCH_REPORTS
302 crDebug("Inserting movq/jmp instead");
303# endif
304 /*add 64bit abs jmp*/
305 patch[0] = 0x49; /*movq %r11,imm64*/
306 patch[1] = 0xBB;
307 crMemcpy(&patch[2], &pStart, 8);
308 patch[10] = 0x41; /*jmp *%r11*/
309 patch[11] = 0xFF;
310 patch[12] = 0xE3;
311 pStart = &patch[0];
312 pEnd = &patch[FAKEDRI_JMP64_PATCH_SIZE];
313 }
314 else
315 {
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);
319# endif
320 /*Add patch node to repatch with chain jmps in 2nd pass*/
321 pNode = (FAKEDRI_PatchNode *)crAlloc(sizeof(FAKEDRI_PatchNode));
322 if (!pNode)
323 {
324 crError("Not enough memory.");
325 return;
326 }
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;
334 return;
335 }
336 }
337 else
338#endif
339 {
340#ifndef VBOX_NO_MESA_PATCH_REPORTS
341 crDebug("Inserting jmp[q] with shift %p instead", shift);
342#endif
343 patch[0] = 0xE9;
344 crMemcpy(&patch[1], &shift, 4);
345 pStart = &patch[0];
346 pEnd = &patch[5];
347 }
348 }
349
350 vboxApplyPatch(psFuncName, dlip.dli_saddr, pStart, pEnd-pStart);
351
352#ifdef RT_ARCH_AMD64
353 /*Add rest of mesa function body to free list*/
354 if (sym->st_size-(pEnd-pStart)>=FAKEDRI_JMP64_PATCH_SIZE)
355 {
356 FAKEDRI_PatchNode *pNode = (FAKEDRI_PatchNode *)crAlloc(sizeof(FAKEDRI_PatchNode));
357 if (pNode)
358 {
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;
365 g_pFreeList = pNode;
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);
369# endif
370 }
371 }
372#endif
373}
374
375#ifdef RT_ARCH_AMD64
376static void
377vboxRepatchMesaExports(void)
378{
379 FAKEDRI_PatchNode *pFreeNode, *pPatchNode;
380 int64_t offset;
381 char patch[FAKEDRI_JMP64_PATCH_SIZE];
382
383 pPatchNode = g_pRepatchList;
384 while (pPatchNode)
385 {
386# ifndef VBOX_NO_MESA_PATCH_REPORTS
387 crDebug("\nvboxRepatchMesaExports %s", pPatchNode->psFuncName);
388# endif
389 /*find free place in mesa functions, to place 64bit jump to our stub code*/
390 pFreeNode = g_pFreeList;
391 while (pFreeNode)
392 {
393 if (pFreeNode->pDstEnd-pFreeNode->pDstStart>=FAKEDRI_JMP64_PATCH_SIZE)
394 {
395 offset = ((intptr_t)pFreeNode->pDstStart-((intptr_t)pPatchNode->pDstStart+5));
396 if (offset<=INT32_MAX && offset>=INT32_MIN)
397 {
398 break;
399 }
400 }
401 pFreeNode=pFreeNode->pNext;
402 }
403
404 if (!pFreeNode)
405 {
406 crError("Failed to find free space, to place repatch for %s.", pPatchNode->psFuncName);
407 return;
408 }
409
410 /*add 32bit rel jmp, from mesa orginal function to free space in other mesa function*/
411 patch[0] = 0xE9;
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);
416# endif
417 vboxApplyPatch(pPatchNode->psFuncName, pPatchNode->pDstStart, &patch[0], 5);
418
419 /*add 64bit abs jmp, from free space to our stub code*/
420 patch[0] = 0x49; /*movq %r11,imm64*/
421 patch[1] = 0xBB;
422 crMemcpy(&patch[2], &pPatchNode->pSrcStart, 8);
423 patch[10] = 0x41; /*jmp *%r11*/
424 patch[11] = 0xFF;
425 patch[12] = 0xE3;
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);
429# endif
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;
433
434 pPatchNode = pPatchNode->pNext;
435 }
436}
437
438static void
439vboxFakeDriFreeList(FAKEDRI_PatchNode *pList)
440{
441 FAKEDRI_PatchNode *pNode;
442
443 while (pList)
444 {
445 pNode=pList;
446 pList=pNode->pNext;
447 crFree(pNode);
448 }
449}
450#endif
451
452#ifdef VBOX_OGL_GLX_USE_CSTUBS
453static void
454# define GLXAPI_ENTRY(Func) vboxPatchMesaExport("glX"#Func, &vbox_glX##Func, NULL);
455vboxPatchMesaExports()
456#else
457static void
458# define GLXAPI_ENTRY(Func) vboxPatchMesaExport("glX"#Func, &vbox_glX##Func, &vbox_glX##Func##_EndProc);
459vboxPatchMesaExports()
460#endif
461{
462 crDebug("Patching mesa glx entries");
463 #include "fakedri_glxfuncsList.h"
464
465#ifdef RT_ARCH_AMD64
466 vboxRepatchMesaExports();
467 vboxFakeDriFreeList(g_pRepatchList);
468 g_pRepatchList = NULL;
469 vboxFakeDriFreeList(g_pFreeList);
470 g_pFreeList = NULL;
471#endif
472}
473#undef GLXAPI_ENTRY
474
475bool vbox_load_sw_dri()
476{
477 const char *libPaths, *p, *next;;
478 char realDriverName[200];
479 void *handle;
480 int len, i;
481
482 /*code from Mesa-7.2/src/glx/x11/dri_common.c:driOpenDriver*/
483
484 libPaths = NULL;
485 if (geteuid() == getuid()) {
486 /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */
487 libPaths = getenv("LIBGL_DRIVERS_PATH");
488 if (!libPaths)
489 libPaths = getenv("LIBGL_DRIVERS_DIR"); /* deprecated */
490 }
491 if (libPaths == NULL)
492 libPaths = DRI_DEFAULT_DRIVER_DIR;
493
494 handle = NULL;
495 for (p = libPaths; *p; p = next)
496 {
497 next = strchr(p, ':');
498 if (next == NULL)
499 {
500 len = strlen(p);
501 next = p + len;
502 }
503 else
504 {
505 len = next - p;
506 next++;
507 }
508
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);
512 if (handle) break;
513 }
514
515 /*end code*/
516
517 if (handle) gppSwDriExternsion = dlsym(handle, "__driDriverExtensions");
518
519 if (!gppSwDriExternsion)
520 {
521 crDebug("%s doesn't export __driDriverExtensions", realDriverName);
522 return false;
523 }
524 crDebug("loaded %s", realDriverName);
525
526 for (i = 0; gppSwDriExternsion[i]; i++)
527 {
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];
532 }
533
534 return gpSwDriCoreExternsion && gpSwDriSwrastExtension;
535}
536
537void __attribute__ ((constructor)) vbox_install_into_mesa(void)
538{
539 {
540#ifdef _X_ATTRIBUTE_PRINTF
541 void (*pxf86Msg)(MessageType type, const char *format, ...) _X_ATTRIBUTE_PRINTF(2,3);
542#else
543 void (*pxf86Msg)(MessageType type, const char *format, ...) _printf_attribute(2,3);
544#endif
545
546 pxf86Msg = dlsym(RTLD_DEFAULT, "xf86Msg");
547 if (pxf86Msg)
548 {
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);
552
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;
555 return;
556 }
557 }
558
559 if (!stubInit())
560 {
561 crDebug("vboxdriInitScreen: stubInit failed");
562 return;
563 }
564
565 /* Load swrast_dri.so to proxy dri related calls there. */
566 if (!vbox_load_sw_dri())
567 {
568 crDebug("vboxdriInitScreen: vbox_load_sw_dri failed...going to fail badly");
569 return;
570 }
571
572 /* Handle gl api.
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.
576 */
577 /* Mesa's dispatch table is different across library versions, have to modify mesa's table using offset info functions*/
578 vboxPatchMesaGLAPITable();
579
580 /* Handle glx api.
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)
583 */
584 /* Fill structure used by our assembly stubs */
585 vboxFillGLXAPITable(&glxim);
586 /* Now patch functions exported by libGL.so */
587 vboxPatchMesaExports();
588}
589
590/*
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.
593 */
594
595/* __DRIcoreExtension */
596
597static __DRIscreen *
598vboxdriCreateNewScreen(int screen, int fd, unsigned int sarea_handle,
599 const __DRIextension **extensions, const __DRIconfig ***driverConfigs,
600 void *loaderPrivate)
601{
602 (void) fd;
603 (void) sarea_handle;
604 SWDRI_SAFERET_SWRAST(createNewScreen, screen, extensions, driverConfigs, loaderPrivate);
605}
606
607static void
608vboxdriDestroyScreen(__DRIscreen *screen)
609{
610 SWDRI_SAFECALL_CORE(destroyScreen, screen);
611}
612
613static const __DRIextension **
614vboxdriGetExtensions(__DRIscreen *screen)
615{
616 SWDRI_SAFERET_CORE(getExtensions, screen);
617}
618
619static int
620vboxdriGetConfigAttrib(const __DRIconfig *config,
621 unsigned int attrib,
622 unsigned int *value)
623{
624 SWDRI_SAFERET_CORE(getConfigAttrib, config, attrib, value);
625}
626
627static int
628vboxdriIndexConfigAttrib(const __DRIconfig *config, int index,
629 unsigned int *attrib, unsigned int *value)
630{
631 SWDRI_SAFERET_CORE(indexConfigAttrib, config, index, attrib, value);
632}
633
634static __DRIdrawable *
635vboxdriCreateNewDrawable(__DRIscreen *screen,
636 const __DRIconfig *config,
637 unsigned int drawable_id,
638 unsigned int head,
639 void *loaderPrivate)
640{
641 (void) drawable_id;
642 (void) head;
643 SWDRI_SAFERET_SWRAST(createNewDrawable, screen, config, loaderPrivate);
644}
645
646static void
647vboxdriDestroyDrawable(__DRIdrawable *drawable)
648{
649 SWDRI_SAFECALL_CORE(destroyDrawable, drawable);
650}
651
652static void
653vboxdriSwapBuffers(__DRIdrawable *drawable)
654{
655 SWDRI_SAFECALL_CORE(swapBuffers, drawable);
656}
657
658static __DRIcontext *
659vboxdriCreateNewContext(__DRIscreen *screen,
660 const __DRIconfig *config,
661 __DRIcontext *shared,
662 void *loaderPrivate)
663{
664 SWDRI_SAFERET_CORE(createNewContext, screen, config, shared, loaderPrivate);
665}
666
667static int
668vboxdriCopyContext(__DRIcontext *dest,
669 __DRIcontext *src,
670 unsigned long mask)
671{
672 SWDRI_SAFERET_CORE(copyContext, dest, src, mask);
673}
674
675static void
676vboxdriDestroyContext(__DRIcontext *context)
677{
678 SWDRI_SAFECALL_CORE(destroyContext, context);
679}
680
681static int
682vboxdriBindContext(__DRIcontext *ctx,
683 __DRIdrawable *pdraw,
684 __DRIdrawable *pread)
685{
686 SWDRI_SAFERET_CORE(bindContext, ctx, pdraw, pread);
687}
688
689static int
690vboxdriUnbindContext(__DRIcontext *ctx)
691{
692 SWDRI_SAFERET_CORE(unbindContext, ctx)
693}
694
695/* __DRIlegacyExtension */
696
697static __DRIscreen *
698vboxdriCreateNewScreen_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,
706 void *loaderPrivate)
707{
708 (void) ddx_version;
709 (void) dri_version;
710 (void) frame_buffer;
711 (void) pSAREA;
712 (void) fd;
713 SWDRI_SAFERET_SWRAST(createNewScreen, scrn, extensions, driver_modes, loaderPrivate);
714}
715
716static __DRIdrawable *
717vboxdriCreateNewDrawable_Legacy(__DRIscreen *psp, const __DRIconfig *config,
718 drm_drawable_t hwDrawable, int renderType,
719 const int *attrs, void *data)
720{
721 (void) hwDrawable;
722 (void) renderType;
723 (void) attrs;
724 (void) data;
725 SWDRI_SAFERET_SWRAST(createNewDrawable, psp, config, data);
726}
727
728static __DRIcontext *
729vboxdriCreateNewContext_Legacy(__DRIscreen *psp, const __DRIconfig *config,
730 int render_type, __DRIcontext *shared,
731 drm_context_t hwContext, void *data)
732{
733 (void) render_type;
734 (void) hwContext;
735 return vboxdriCreateNewContext(psp, config, shared, data);
736}
737
738
739static const __DRIlegacyExtension vboxdriLegacyExtension = {
740 { __DRI_LEGACY, __DRI_LEGACY_VERSION },
741 vboxdriCreateNewScreen_Legacy,
742 vboxdriCreateNewDrawable_Legacy,
743 vboxdriCreateNewContext_Legacy
744};
745
746static 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,
755 vboxdriSwapBuffers,
756 vboxdriCreateNewContext,
757 vboxdriCopyContext,
758 vboxdriDestroyContext,
759 vboxdriBindContext,
760 vboxdriUnbindContext
761};
762
763/* This structure is used by dri_util from mesa, don't rename it! */
764DECLEXPORT(const __DRIextension *) __driDriverExtensions[] = {
765 &vboxdriLegacyExtension.base,
766 &vboxdriCoreExtension.base,
767 NULL
768};
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use