Subversion Repositories Kolibri OS

Rev

Rev 4358 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*
  2.  * (C) Copyright IBM Corporation 2002, 2004
  3.  * All Rights Reserved.
  4.  *
  5.  * Permission is hereby granted, free of charge, to any person obtaining a
  6.  * copy of this software and associated documentation files (the "Software"),
  7.  * to deal in the Software without restriction, including without limitation
  8.  * on the rights to use, copy, modify, merge, publish, distribute, sub
  9.  * license, and/or sell copies of the Software, and to permit persons to whom
  10.  * the Software is furnished to do so, subject to the following conditions:
  11.  *
  12.  * The above copyright notice and this permission notice (including the next
  13.  * paragraph) shall be included in all copies or substantial portions of the
  14.  * Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
  19.  * THE AUTHORS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
  20.  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  21.  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  22.  * USE OR OTHER DEALINGS IN THE SOFTWARE.
  23.  */
  24.  
  25. /**
  26.  * \file dri_util.c
  27.  * DRI utility functions.
  28.  *
  29.  * This module acts as glue between GLX and the actual hardware driver.  A DRI
  30.  * driver doesn't really \e have to use any of this - it's optional.  But, some
  31.  * useful stuff is done here that otherwise would have to be duplicated in most
  32.  * drivers.
  33.  *
  34.  * Basically, these utility functions take care of some of the dirty details of
  35.  * screen initialization, context creation, context binding, DRM setup, etc.
  36.  *
  37.  * These functions are compiled into each DRI driver so libGL.so knows nothing
  38.  * about them.
  39.  */
  40.  
  41.  
  42. #include <xf86drm.h>
  43. #include "dri_util.h"
  44. #include "utils.h"
  45. #include "xmlpool.h"
  46. #include "../glsl/glsl_parser_extras.h"
  47.  
  48. PUBLIC const char __dri2ConfigOptions[] =
  49.    DRI_CONF_BEGIN
  50.       DRI_CONF_SECTION_PERFORMANCE
  51.          DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1)
  52.       DRI_CONF_SECTION_END
  53.    DRI_CONF_END;
  54.  
  55. static const uint __dri2NConfigOptions = 1;
  56.  
  57. /*****************************************************************/
  58. /** \name Screen handling functions                              */
  59. /*****************************************************************/
  60. /*@{*/
  61.  
  62. static void
  63. setupLoaderExtensions(__DRIscreen *psp,
  64.                       const __DRIextension **extensions)
  65. {
  66.     int i;
  67.  
  68.     for (i = 0; extensions[i]; i++) {
  69.         if (strcmp(extensions[i]->name, __DRI_DRI2_LOADER) == 0)
  70.             psp->dri2.loader = (__DRIdri2LoaderExtension *) extensions[i];
  71.         if (strcmp(extensions[i]->name, __DRI_IMAGE_LOOKUP) == 0)
  72.             psp->dri2.image = (__DRIimageLookupExtension *) extensions[i];
  73.         if (strcmp(extensions[i]->name, __DRI_USE_INVALIDATE) == 0)
  74.             psp->dri2.useInvalidate = (__DRIuseInvalidateExtension *) extensions[i];
  75.     }
  76. }
  77.  
  78. static __DRIscreen *
  79. dri2CreateNewScreen(int scrn, int fd,
  80.                     const __DRIextension **extensions,
  81.                     const __DRIconfig ***driver_configs, void *data)
  82. {
  83.     static const __DRIextension *emptyExtensionList[] = { NULL };
  84.     __DRIscreen *psp;
  85.     drmVersionPtr version;
  86.  
  87.     psp = calloc(1, sizeof(*psp));
  88.     if (!psp)
  89.         return NULL;
  90.  
  91.     setupLoaderExtensions(psp, extensions);
  92.  
  93.     version = drmGetVersion(fd);
  94.     if (version) {
  95.         psp->drm_version.major = version->version_major;
  96.         psp->drm_version.minor = version->version_minor;
  97.         psp->drm_version.patch = version->version_patchlevel;
  98.         drmFreeVersion(version);
  99.     }
  100.  
  101.     psp->loaderPrivate = data;
  102.  
  103.     psp->extensions = emptyExtensionList;
  104.     psp->fd = fd;
  105.     psp->myNum = scrn;
  106.  
  107.     psp->api_mask = (1 << __DRI_API_OPENGL);
  108.  
  109.     *driver_configs = driDriverAPI.InitScreen(psp);
  110.     if (*driver_configs == NULL) {
  111.         free(psp);
  112.         return NULL;
  113.     }
  114.  
  115.     driParseOptionInfo(&psp->optionInfo, __dri2ConfigOptions, __dri2NConfigOptions);
  116.     driParseConfigFiles(&psp->optionCache, &psp->optionInfo, psp->myNum, "dri2");
  117.  
  118.     return psp;
  119. }
  120.  
  121. /**
  122.  * Destroy the per-screen private information.
  123.  *
  124.  * \internal
  125.  * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
  126.  * drmClose(), and finally frees \p screenPrivate.
  127.  */
  128. static void driDestroyScreen(__DRIscreen *psp)
  129. {
  130.     if (psp) {
  131.         /* No interaction with the X-server is possible at this point.  This
  132.          * routine is called after XCloseDisplay, so there is no protocol
  133.          * stream open to the X-server anymore.
  134.          */
  135.  
  136.        _mesa_destroy_shader_compiler();
  137.  
  138.         driDriverAPI.DestroyScreen(psp);
  139.  
  140.         driDestroyOptionCache(&psp->optionCache);
  141.         driDestroyOptionInfo(&psp->optionInfo);
  142.  
  143.         free(psp);
  144.     }
  145. }
  146.  
  147. static const __DRIextension **driGetExtensions(__DRIscreen *psp)
  148. {
  149.     return psp->extensions;
  150. }
  151.  
  152. /*@}*/
  153.  
  154.  
  155. /*****************************************************************/
  156. /** \name Context handling functions                             */
  157. /*****************************************************************/
  158. /*@{*/
  159.  
  160. static __DRIcontext *
  161. dri2CreateContextAttribs(__DRIscreen *screen, int api,
  162.                          const __DRIconfig *config,
  163.                          __DRIcontext *shared,
  164.                          unsigned num_attribs,
  165.                          const uint32_t *attribs,
  166.                          unsigned *error,
  167.                          void *data)
  168. {
  169.     __DRIcontext *context;
  170.     const struct gl_config *modes = (config != NULL) ? &config->modes : NULL;
  171.     void *shareCtx = (shared != NULL) ? shared->driverPrivate : NULL;
  172.     gl_api mesa_api;
  173.     unsigned major_version = 1;
  174.     unsigned minor_version = 0;
  175.     uint32_t flags = 0;
  176.  
  177.     assert((num_attribs == 0) || (attribs != NULL));
  178.  
  179.     if (!(screen->api_mask & (1 << api))) {
  180.         *error = __DRI_CTX_ERROR_BAD_API;
  181.         return NULL;
  182.     }
  183.  
  184.     switch (api) {
  185.     case __DRI_API_OPENGL:
  186.         mesa_api = API_OPENGL_COMPAT;
  187.         break;
  188.     case __DRI_API_GLES:
  189.         mesa_api = API_OPENGLES;
  190.         break;
  191.     case __DRI_API_GLES2:
  192.     case __DRI_API_GLES3:
  193.         mesa_api = API_OPENGLES2;
  194.         break;
  195.     case __DRI_API_OPENGL_CORE:
  196.         mesa_api = API_OPENGL_CORE;
  197.         break;
  198.     default:
  199.         *error = __DRI_CTX_ERROR_BAD_API;
  200.         return NULL;
  201.     }
  202.  
  203.     for (unsigned i = 0; i < num_attribs; i++) {
  204.         switch (attribs[i * 2]) {
  205.         case __DRI_CTX_ATTRIB_MAJOR_VERSION:
  206.             major_version = attribs[i * 2 + 1];
  207.             break;
  208.         case __DRI_CTX_ATTRIB_MINOR_VERSION:
  209.             minor_version = attribs[i * 2 + 1];
  210.             break;
  211.         case __DRI_CTX_ATTRIB_FLAGS:
  212.             flags = attribs[i * 2 + 1];
  213.             break;
  214.         default:
  215.             /* We can't create a context that satisfies the requirements of an
  216.              * attribute that we don't understand.  Return failure.
  217.              */
  218.             assert(!"Should not get here.");
  219.             *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE;
  220.             return NULL;
  221.         }
  222.     }
  223.  
  224.     /* Mesa does not support the GL_ARB_compatibilty extension or the
  225.      * compatibility profile.  This means that we treat a API_OPENGL_COMPAT 3.1 as
  226.      * API_OPENGL_CORE and reject API_OPENGL_COMPAT 3.2+.
  227.      */
  228.     if (mesa_api == API_OPENGL_COMPAT && major_version == 3 && minor_version == 1)
  229.        mesa_api = API_OPENGL_CORE;
  230.  
  231.     if (mesa_api == API_OPENGL_COMPAT
  232.         && ((major_version > 3)
  233.             || (major_version == 3 && minor_version >= 2))) {
  234.        *error = __DRI_CTX_ERROR_BAD_API;
  235.        return NULL;
  236.     }
  237.  
  238.     /* The EGL_KHR_create_context spec says:
  239.      *
  240.      *     "Flags are only defined for OpenGL context creation, and specifying
  241.      *     a flags value other than zero for other types of contexts,
  242.      *     including OpenGL ES contexts, will generate an error."
  243.      *
  244.      * The GLX_EXT_create_context_es2_profile specification doesn't say
  245.      * anything specific about this case.  However, none of the known flags
  246.      * have any meaning in an ES context, so this seems safe.
  247.      */
  248.     if (mesa_api != API_OPENGL_COMPAT
  249.         && mesa_api != API_OPENGL_CORE
  250.         && flags != 0) {
  251.         *error = __DRI_CTX_ERROR_BAD_FLAG;
  252.         return NULL;
  253.     }
  254.  
  255.     /* There are no forward-compatible contexts before OpenGL 3.0.  The
  256.      * GLX_ARB_create_context spec says:
  257.      *
  258.      *     "Forward-compatible contexts are defined only for OpenGL versions
  259.      *     3.0 and later."
  260.      *
  261.      * Forward-looking contexts are supported by silently converting the
  262.      * requested API to API_OPENGL_CORE.
  263.      *
  264.      * In Mesa, a debug context is the same as a regular context.
  265.      */
  266.     if ((flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0) {
  267.        mesa_api = API_OPENGL_CORE;
  268.     }
  269.  
  270.     if ((flags & ~(__DRI_CTX_FLAG_DEBUG | __DRI_CTX_FLAG_FORWARD_COMPATIBLE))
  271.         != 0) {
  272.         *error = __DRI_CTX_ERROR_UNKNOWN_FLAG;
  273.         return NULL;
  274.     }
  275.  
  276.     context = calloc(1, sizeof *context);
  277.     if (!context) {
  278.         *error = __DRI_CTX_ERROR_NO_MEMORY;
  279.         return NULL;
  280.     }
  281.  
  282.     context->loaderPrivate = data;
  283.  
  284.     context->driScreenPriv = screen;
  285.     context->driDrawablePriv = NULL;
  286.     context->driReadablePriv = NULL;
  287.  
  288.     if (!driDriverAPI.CreateContext(mesa_api, modes, context,
  289.                                     major_version, minor_version,
  290.                                     flags, error, shareCtx) ) {
  291.         free(context);
  292.         return NULL;
  293.     }
  294.  
  295.     *error = __DRI_CTX_ERROR_SUCCESS;
  296.     return context;
  297. }
  298.  
  299. static __DRIcontext *
  300. dri2CreateNewContextForAPI(__DRIscreen *screen, int api,
  301.                            const __DRIconfig *config,
  302.                            __DRIcontext *shared, void *data)
  303. {
  304.     unsigned error;
  305.  
  306.     return dri2CreateContextAttribs(screen, api, config, shared, 0, NULL,
  307.                                     &error, data);
  308. }
  309.  
  310. static __DRIcontext *
  311. dri2CreateNewContext(__DRIscreen *screen, const __DRIconfig *config,
  312.                       __DRIcontext *shared, void *data)
  313. {
  314.     return dri2CreateNewContextForAPI(screen, __DRI_API_OPENGL,
  315.                                       config, shared, data);
  316. }
  317.  
  318. /**
  319.  * Destroy the per-context private information.
  320.  *
  321.  * \internal
  322.  * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
  323.  * drmDestroyContext(), and finally frees \p contextPrivate.
  324.  */
  325. static void
  326. driDestroyContext(__DRIcontext *pcp)
  327. {
  328.     if (pcp) {
  329.         driDriverAPI.DestroyContext(pcp);
  330.         free(pcp);
  331.     }
  332. }
  333.  
  334. static int
  335. driCopyContext(__DRIcontext *dest, __DRIcontext *src, unsigned long mask)
  336. {
  337.     (void) dest;
  338.     (void) src;
  339.     (void) mask;
  340.     return GL_FALSE;
  341. }
  342.  
  343. /*@}*/
  344.  
  345.  
  346. /*****************************************************************/
  347. /** \name Context (un)binding functions                          */
  348. /*****************************************************************/
  349. /*@{*/
  350.  
  351. static void dri_get_drawable(__DRIdrawable *pdp);
  352. static void dri_put_drawable(__DRIdrawable *pdp);
  353.  
  354. /**
  355.  * This function takes both a read buffer and a draw buffer.  This is needed
  356.  * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
  357.  * function.
  358.  */
  359. static int driBindContext(__DRIcontext *pcp,
  360.                           __DRIdrawable *pdp,
  361.                           __DRIdrawable *prp)
  362. {
  363.     /*
  364.     ** Assume error checking is done properly in glXMakeCurrent before
  365.     ** calling driUnbindContext.
  366.     */
  367.  
  368.     if (!pcp)
  369.         return GL_FALSE;
  370.  
  371.     /* Bind the drawable to the context */
  372.     pcp->driDrawablePriv = pdp;
  373.     pcp->driReadablePriv = prp;
  374.     if (pdp) {
  375.         pdp->driContextPriv = pcp;
  376.         dri_get_drawable(pdp);
  377.     }
  378.     if (prp && pdp != prp) {
  379.         dri_get_drawable(prp);
  380.     }
  381.  
  382.     return driDriverAPI.MakeCurrent(pcp, pdp, prp);
  383. }
  384.  
  385. /**
  386.  * Unbind context.
  387.  *
  388.  * \param scrn the screen.
  389.  * \param gc context.
  390.  *
  391.  * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
  392.  *
  393.  * \internal
  394.  * This function calls __DriverAPIRec::UnbindContext, and then decrements
  395.  * __DRIdrawableRec::refcount which must be non-zero for a successful
  396.  * return.
  397.  *
  398.  * While casting the opaque private pointers associated with the parameters
  399.  * into their respective real types it also assures they are not \c NULL.
  400.  */
  401. static int driUnbindContext(__DRIcontext *pcp)
  402. {
  403.     __DRIdrawable *pdp;
  404.     __DRIdrawable *prp;
  405.  
  406.     /*
  407.     ** Assume error checking is done properly in glXMakeCurrent before
  408.     ** calling driUnbindContext.
  409.     */
  410.  
  411.     if (pcp == NULL)
  412.         return GL_FALSE;
  413.  
  414.     pdp = pcp->driDrawablePriv;
  415.     prp = pcp->driReadablePriv;
  416.  
  417.     /* already unbound */
  418.     if (!pdp && !prp)
  419.         return GL_TRUE;
  420.  
  421.     driDriverAPI.UnbindContext(pcp);
  422.  
  423.     assert(pdp);
  424.     if (pdp->refcount == 0) {
  425.         /* ERROR!!! */
  426.         return GL_FALSE;
  427.     }
  428.  
  429.     dri_put_drawable(pdp);
  430.  
  431.     if (prp != pdp) {
  432.         if (prp->refcount == 0) {
  433.             /* ERROR!!! */
  434.             return GL_FALSE;
  435.         }
  436.  
  437.         dri_put_drawable(prp);
  438.     }
  439.  
  440.     /* XXX this is disabled so that if we call SwapBuffers on an unbound
  441.      * window we can determine the last context bound to the window and
  442.      * use that context's lock. (BrianP, 2-Dec-2000)
  443.      */
  444.     pcp->driDrawablePriv = NULL;
  445.     pcp->driReadablePriv = NULL;
  446.  
  447.     return GL_TRUE;
  448. }
  449.  
  450. /*@}*/
  451.  
  452.  
  453. static void dri_get_drawable(__DRIdrawable *pdp)
  454. {
  455.     pdp->refcount++;
  456. }
  457.  
  458. static void dri_put_drawable(__DRIdrawable *pdp)
  459. {
  460.     if (pdp) {
  461.         pdp->refcount--;
  462.         if (pdp->refcount)
  463.             return;
  464.  
  465.         driDriverAPI.DestroyBuffer(pdp);
  466.         free(pdp);
  467.     }
  468. }
  469.  
  470. static __DRIdrawable *
  471. dri2CreateNewDrawable(__DRIscreen *screen,
  472.                       const __DRIconfig *config,
  473.                       void *data)
  474. {
  475.     __DRIdrawable *pdraw;
  476.  
  477.     pdraw = malloc(sizeof *pdraw);
  478.     if (!pdraw)
  479.         return NULL;
  480.  
  481.     pdraw->loaderPrivate = data;
  482.  
  483.     pdraw->driScreenPriv = screen;
  484.     pdraw->driContextPriv = NULL;
  485.     pdraw->refcount = 0;
  486.     pdraw->lastStamp = 0;
  487.     pdraw->w = 0;
  488.     pdraw->h = 0;
  489.  
  490.     dri_get_drawable(pdraw);
  491.  
  492.     if (!driDriverAPI.CreateBuffer(screen, pdraw, &config->modes, GL_FALSE)) {
  493.        free(pdraw);
  494.        return NULL;
  495.     }
  496.  
  497.     pdraw->dri2.stamp = pdraw->lastStamp + 1;
  498.  
  499.     return pdraw;
  500. }
  501.  
  502. static void
  503. driDestroyDrawable(__DRIdrawable *pdp)
  504. {
  505.     dri_put_drawable(pdp);
  506. }
  507.  
  508. static __DRIbuffer *
  509. dri2AllocateBuffer(__DRIscreen *screen,
  510.                    unsigned int attachment, unsigned int format,
  511.                    int width, int height)
  512. {
  513.     return driDriverAPI.AllocateBuffer(screen, attachment, format,
  514.                                        width, height);
  515. }
  516.  
  517. static void
  518. dri2ReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer)
  519. {
  520.     driDriverAPI.ReleaseBuffer(screen, buffer);
  521. }
  522.  
  523.  
  524. static int
  525. dri2ConfigQueryb(__DRIscreen *screen, const char *var, GLboolean *val)
  526. {
  527.    if (!driCheckOption(&screen->optionCache, var, DRI_BOOL))
  528.       return -1;
  529.  
  530.    *val = driQueryOptionb(&screen->optionCache, var);
  531.  
  532.    return 0;
  533. }
  534.  
  535. static int
  536. dri2ConfigQueryi(__DRIscreen *screen, const char *var, GLint *val)
  537. {
  538.    if (!driCheckOption(&screen->optionCache, var, DRI_INT) &&
  539.        !driCheckOption(&screen->optionCache, var, DRI_ENUM))
  540.       return -1;
  541.  
  542.     *val = driQueryOptioni(&screen->optionCache, var);
  543.  
  544.     return 0;
  545. }
  546.  
  547. static int
  548. dri2ConfigQueryf(__DRIscreen *screen, const char *var, GLfloat *val)
  549. {
  550.    if (!driCheckOption(&screen->optionCache, var, DRI_FLOAT))
  551.       return -1;
  552.  
  553.     *val = driQueryOptionf(&screen->optionCache, var);
  554.  
  555.     return 0;
  556. }
  557.  
  558. static unsigned int
  559. dri2GetAPIMask(__DRIscreen *screen)
  560. {
  561.     return screen->api_mask;
  562. }
  563.  
  564.  
  565. /** Core interface */
  566. const __DRIcoreExtension driCoreExtension = {
  567.     .base = { __DRI_CORE, __DRI_CORE_VERSION },
  568.  
  569.     .createNewScreen            = NULL,
  570.     .destroyScreen              = driDestroyScreen,
  571.     .getExtensions              = driGetExtensions,
  572.     .getConfigAttrib            = driGetConfigAttrib,
  573.     .indexConfigAttrib          = driIndexConfigAttrib,
  574.     .createNewDrawable          = NULL,
  575.     .destroyDrawable            = driDestroyDrawable,
  576.     .swapBuffers                = NULL,
  577.     .createNewContext           = NULL,
  578.     .copyContext                = driCopyContext,
  579.     .destroyContext             = driDestroyContext,
  580.     .bindContext                = driBindContext,
  581.     .unbindContext              = driUnbindContext
  582. };
  583.  
  584. /** DRI2 interface */
  585. const __DRIdri2Extension driDRI2Extension = {
  586.     .base = { __DRI_DRI2, 3 },
  587.  
  588.     .createNewScreen            = dri2CreateNewScreen,
  589.     .createNewDrawable          = dri2CreateNewDrawable,
  590.     .createNewContext           = dri2CreateNewContext,
  591.     .getAPIMask                 = dri2GetAPIMask,
  592.     .createNewContextForAPI     = dri2CreateNewContextForAPI,
  593.     .allocateBuffer             = dri2AllocateBuffer,
  594.     .releaseBuffer              = dri2ReleaseBuffer,
  595.     .createContextAttribs       = dri2CreateContextAttribs
  596. };
  597.  
  598. const __DRI2configQueryExtension dri2ConfigQueryExtension = {
  599.    .base = { __DRI2_CONFIG_QUERY, __DRI2_CONFIG_QUERY_VERSION },
  600.  
  601.    .configQueryb        = dri2ConfigQueryb,
  602.    .configQueryi        = dri2ConfigQueryi,
  603.    .configQueryf        = dri2ConfigQueryf,
  604. };
  605.  
  606. void
  607. dri2InvalidateDrawable(__DRIdrawable *drawable)
  608. {
  609.     drawable->dri2.stamp++;
  610. }
  611.  
  612. /**
  613.  * Check that the gl_framebuffer associated with dPriv is the right size.
  614.  * Resize the gl_framebuffer if needed.
  615.  * It's expected that the dPriv->driverPrivate member points to a
  616.  * gl_framebuffer object.
  617.  */
  618. void
  619. driUpdateFramebufferSize(struct gl_context *ctx, const __DRIdrawable *dPriv)
  620. {
  621.    struct gl_framebuffer *fb = (struct gl_framebuffer *) dPriv->driverPrivate;
  622.    if (fb && (dPriv->w != fb->Width || dPriv->h != fb->Height)) {
  623.       ctx->Driver.ResizeBuffers(ctx, fb, dPriv->w, dPriv->h);
  624.       /* if the driver needs the hw lock for ResizeBuffers, the drawable
  625.          might have changed again by now */
  626.       assert(fb->Width == dPriv->w);
  627.       assert(fb->Height == dPriv->h);
  628.    }
  629. }
  630.  
  631. int atexit(void (*func)(void))
  632. {
  633.     return 0;
  634. }
  635.