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