Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (c) 2012 Intel Corporation. All Rights Reserved.
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the
  6.  * "Software"), to deal in the Software without restriction, including
  7.  * without limitation the rights to use, copy, modify, merge, publish,
  8.  * distribute, sub license, and/or sell copies of the Software, and to
  9.  * permit persons to whom the Software is furnished to do so, subject to
  10.  * the following conditions:
  11.  *
  12.  * The above copyright notice and this permission notice (including the
  13.  * next paragraph) shall be included in all copies or substantial portions
  14.  * of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  17.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  18.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  19.  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
  20.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  21.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  22.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23.  */
  24. #include <stdlib.h>
  25. #include <fcntl.h>
  26. #include <unistd.h>
  27. #include <assert.h>
  28.  
  29. #include <xf86drm.h>
  30.  
  31. #include <X11/Xlibint.h>
  32. #include <X11/Xlib.h>
  33. #include "va.h"
  34. #include "va_backend.h"
  35.  
  36. #include "va_dri2.h"
  37. #include "va_dri2tokens.h"
  38. #include "va_dricommon.h"
  39.  
  40. #define __DRI_BUFFER_FRONT_LEFT         0
  41. #define __DRI_BUFFER_BACK_LEFT          1
  42. #define __DRI_BUFFER_FRONT_RIGHT        2
  43. #define __DRI_BUFFER_BACK_RIGHT         3
  44. #define __DRI_BUFFER_DEPTH              4
  45. #define __DRI_BUFFER_STENCIL            5
  46. #define __DRI_BUFFER_ACCUM              6
  47. #define __DRI_BUFFER_FAKE_FRONT_LEFT    7
  48. #define __DRI_BUFFER_FAKE_FRONT_RIGHT   8
  49.  
  50. struct dri2_drawable
  51. {
  52.     struct dri_drawable base;
  53.     union dri_buffer buffers[5];
  54.     int width;
  55.     int height;
  56.     int has_backbuffer;
  57.     int back_index;
  58.     int front_index;
  59. };
  60.  
  61. static int gsDRI2SwapAvailable;
  62.  
  63. static struct dri_drawable *
  64. dri2CreateDrawable(VADriverContextP ctx, XID x_drawable)
  65. {
  66.     struct dri2_drawable *dri2_drawable;
  67.  
  68.     dri2_drawable = calloc(1, sizeof(*dri2_drawable));
  69.  
  70.     if (!dri2_drawable)
  71.         return NULL;
  72.  
  73.     dri2_drawable->base.x_drawable = x_drawable;
  74.     dri2_drawable->base.x = 0;
  75.     dri2_drawable->base.y = 0;
  76.     VA_DRI2CreateDrawable(ctx->native_dpy, x_drawable);
  77.  
  78.     return &dri2_drawable->base;
  79. }
  80.  
  81. static void
  82. dri2DestroyDrawable(VADriverContextP ctx, struct dri_drawable *dri_drawable)
  83. {
  84.     VA_DRI2DestroyDrawable(ctx->native_dpy, dri_drawable->x_drawable);
  85.     free(dri_drawable);
  86. }
  87.  
  88. static void
  89. dri2SwapBuffer(VADriverContextP ctx, struct dri_drawable *dri_drawable)
  90. {
  91.     struct dri2_drawable *dri2_drawable = (struct dri2_drawable *)dri_drawable;
  92.     XRectangle xrect;
  93.     XserverRegion region;
  94.  
  95.     if (dri2_drawable->has_backbuffer) {
  96.         if (gsDRI2SwapAvailable) {
  97.             CARD64 ret;
  98.             VA_DRI2SwapBuffers(ctx->native_dpy, dri_drawable->x_drawable, 0, 0,
  99.                                0, &ret);
  100.         } else {
  101.             xrect.x = 0;
  102.             xrect.y = 0;
  103.             xrect.width = dri2_drawable->width;
  104.             xrect.height = dri2_drawable->height;
  105.  
  106.             region = XFixesCreateRegion(ctx->native_dpy, &xrect, 1);
  107.             VA_DRI2CopyRegion(ctx->native_dpy, dri_drawable->x_drawable, region,
  108.                               DRI2BufferFrontLeft, DRI2BufferBackLeft);
  109.             XFixesDestroyRegion(ctx->native_dpy, region);
  110.         }
  111.     }
  112. }
  113.  
  114. static union dri_buffer *
  115. dri2GetRenderingBuffer(VADriverContextP ctx, struct dri_drawable *dri_drawable)
  116. {
  117.     struct dri2_drawable *dri2_drawable = (struct dri2_drawable *)dri_drawable;
  118.     int i;
  119.     int count;
  120.     unsigned int attachments[5];
  121.     VA_DRI2Buffer *buffers;
  122.    
  123.     i = 0;
  124.     if (dri_drawable->is_window)
  125.         attachments[i++] = __DRI_BUFFER_BACK_LEFT;
  126.     else
  127.         attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
  128.  
  129.     buffers = VA_DRI2GetBuffers(ctx->native_dpy, dri_drawable->x_drawable,
  130.                              &dri2_drawable->width, &dri2_drawable->height,
  131.                              attachments, i, &count);
  132.     assert(buffers);
  133.     if (buffers == NULL)
  134.         return NULL;
  135.  
  136.     dri2_drawable->has_backbuffer = 0;
  137.  
  138.     for (i = 0; i < count; i++) {
  139.         dri2_drawable->buffers[i].dri2.attachment = buffers[i].attachment;
  140.         dri2_drawable->buffers[i].dri2.name = buffers[i].name;
  141.         dri2_drawable->buffers[i].dri2.pitch = buffers[i].pitch;
  142.         dri2_drawable->buffers[i].dri2.cpp = buffers[i].cpp;
  143.         dri2_drawable->buffers[i].dri2.flags = buffers[i].flags;
  144.        
  145.         if (buffers[i].attachment == __DRI_BUFFER_BACK_LEFT) {
  146.             dri2_drawable->has_backbuffer = 1;
  147.             dri2_drawable->back_index = i;
  148.         }
  149.  
  150.         if (buffers[i].attachment == __DRI_BUFFER_FRONT_LEFT)
  151.             dri2_drawable->front_index = i;
  152.     }
  153.    
  154.     dri_drawable->width = dri2_drawable->width;
  155.     dri_drawable->height = dri2_drawable->height;
  156.     Xfree(buffers);
  157.  
  158.     if (dri2_drawable->has_backbuffer)
  159.         return &dri2_drawable->buffers[dri2_drawable->back_index];
  160.  
  161.     return &dri2_drawable->buffers[dri2_drawable->front_index];
  162. }
  163.  
  164. void
  165. dri2Close(VADriverContextP ctx)
  166. {
  167.     struct dri_state *dri_state = (struct dri_state *)ctx->drm_state;
  168.  
  169.     free_drawable_hashtable(ctx);
  170.  
  171.     if (dri_state->base.fd >= 0);
  172.         close(dri_state->base.fd);
  173. }
  174.  
  175. Bool
  176. isDRI2Connected(VADriverContextP ctx, char **driver_name)
  177. {
  178.     struct dri_state *dri_state = (struct dri_state *)ctx->drm_state;
  179.     int major, minor;
  180.     int error_base;
  181.     int event_base;
  182.     char *device_name = NULL;
  183.     drm_magic_t magic;        
  184.     *driver_name = NULL;
  185.     dri_state->base.fd = -1;
  186.     dri_state->base.auth_type = VA_NONE;
  187.     if (!VA_DRI2QueryExtension(ctx->native_dpy, &event_base, &error_base))
  188.         goto err_out;
  189.  
  190.     if (!VA_DRI2QueryVersion(ctx->native_dpy, &major, &minor))
  191.         goto err_out;
  192.  
  193.  
  194.     if (!VA_DRI2Connect(ctx->native_dpy, RootWindow(ctx->native_dpy, ctx->x11_screen),
  195.                      driver_name, &device_name))
  196.         goto err_out;
  197.  
  198.     dri_state->base.fd = open(device_name, O_RDWR);
  199.     assert(dri_state->base.fd >= 0);
  200.  
  201.     if (dri_state->base.fd < 0)
  202.         goto err_out;
  203.  
  204.     if (drmGetMagic(dri_state->base.fd, &magic))
  205.         goto err_out;
  206.  
  207.     if (!VA_DRI2Authenticate(ctx->native_dpy, RootWindow(ctx->native_dpy, ctx->x11_screen),
  208.                           magic))
  209.         goto err_out;
  210.  
  211.     dri_state->base.auth_type = VA_DRI2;
  212.     dri_state->createDrawable = dri2CreateDrawable;
  213.     dri_state->destroyDrawable = dri2DestroyDrawable;
  214.     dri_state->swapBuffer = dri2SwapBuffer;
  215.     dri_state->getRenderingBuffer = dri2GetRenderingBuffer;
  216.     dri_state->close = dri2Close;
  217.     gsDRI2SwapAvailable = (minor >= 2);
  218.  
  219.     if (device_name)
  220.         Xfree(device_name);
  221.  
  222.     return True;
  223.  
  224. err_out:
  225.     if (device_name)
  226.         Xfree(device_name);
  227.  
  228.     if (*driver_name)
  229.         Xfree(*driver_name);
  230.  
  231.     if (dri_state->base.fd >= 0)
  232.         close(dri_state->base.fd);
  233.  
  234.     *driver_name = NULL;
  235.     dri_state->base.fd = -1;
  236.    
  237.     return False;
  238. }
  239.  
  240.